# -*- coding: utf-8 -*-
import sys, os
project_home = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../'))
if project_home not in sys.path:
    sys.path.insert(0, project_home)

from flask_testing import TestCase
import unittest

import regex as re

import referencesrv.app as app
from referencesrv.resolver.authors import get_author_pattern, get_authors, normalize_single_author, \
    normalize_author_list, get_first_author, get_first_author_last_name, count_matching_authors, \
    add_author_evidence
from referencesrv.resolver.common import Evidences, NotResolved, Undecidable, NoSolution, DeferredSourceMatcher, \
    SOURCE_MATCHER, Solution, Hypothesis
from referencesrv.resolver.pytrigdict import get_trigrams, TrigIndex, Trigdict
from referencesrv.resolver.sourcematchers import TrigdictSourceMatcher, SourceMatcher
from referencesrv.resolver.scoring import get_score_for_reference_identifier, get_score_for_input_fields, \
    get_score_for_reference_identifier, get_book_score_for_input_fields, get_thesis_score_for_input_fields
from referencesrv.resolver.journalfield import get_best_bibstem_for, add_volume_evidence, clean_ads_page, \
    compute_page_delta, add_page_evidence, compute_pubstring_statistics, string_similarity, add_publication_evidence, \
    has_word, has_thesis_indicators, cook_title_string
from referencesrv.resolver.solve import make_solr_condition, inspect_doubtful_solutions, inspect_ambiguous_solutions, \
    choose_solution, solve_reference
from referencesrv.resolver.hypotheses import Hypotheses
from referencesrv.resolver.solrquery import Querier
from referencesrv.resolver.specialrules import iter_journal_specific_hypotheses, get_score_for_baas_match
from referencesrv.resolver.sourcematchers import load_source_matcher

class TestResolver(TestCase):

    def create_app(self):
        self.current_app = app.create_app(**{
            'REFERENCE_SERVICE_LIVE': False
           })
        return self.current_app

    def test_get_author_pattern(self):
        """
        Test the return value to be re.compile
        """
        ref_string = "Demleitner, M., Accomazzi, A., Eichhorn, G., et al. 2001, Astronomical Data Analysis Software and Systems X, 238, 321"
        retype = type(re.compile('hello, world'))

        self.assertEqual(isinstance(get_author_pattern(ref_string), retype), True)

    def test_get_authors(self):
        """
        test get_authors
        """
        # when there is no comma before the and
        self.assertEqual(get_authors(u'S. Kung and F. Bayer: "Collected Junk", A&A 2009'), 'S. Kung and F. Bayer')
        # when there is a comma after both lastname and first initials
        self.assertEqual(get_authors(u'Przybilla, N., & Maeder, A. 2010'), 'Przybilla, N., & Maeder, A.')
        # when initials are trailing and there is no dot, recognized first author lastname only
        self.assertEqual(get_authors(u'Przybilla N & Maeder A 2010'), 'Przybilla')
        # when initials are leading and there are no dots, recognized first author lastname only
        self.assertTrue(get_authors('N Przybilla & A Maeder 2010'), 'Przybilla')
        # where there is a `Collaboration` and also `and xxx colleagues` in the list of authors
        self.assertEqual(get_authors(u'Gaia Collaboration, and 625 colleagues 2016. The Gaia mission. Astronomy and Astrophysics 595, A1.'),
                         'Gaia Collaboration, and 625 colleagues')
        # where there is a `co-authors` in the list of authors
        self.assertEqual(get_authors(u'N., Zhao, Y., Diaz-Santos, T., and 18 co-authors, 2017, "ApJS" 230, 1'),
                         'N., Zhao, Y., Diaz-Santos, T., and 18 co-authors')

    def test_normalize_single_author(self):
        """
        Test the return value of a normalized form for a single author string
        """
        ref_string = "Henneken, E.~A., Muench, G., Holm Nielsen, L., Blanco-Cuaresma, S., Accomazzi, A. 2019. Capturing Software Citations in Astronomy and Planetary Sciences. Lunar and Planetary Science Conference 1569."
        normalized = "henneken, e.~a., muench, g., holm nielsen, l., blanco cuaresma, s., accomazzi, a. 2019. capturing software citations in astronomy and planetary sciences. lunar and planetary science conference 1569."
        self.assertEqual(normalize_single_author(ref_string), normalized)

    def test_normalize_author_list(self):
        """
        Ensure that authorString is returned in the form AuthorLast1; AuthorLast2
        """
        self.assertEqual(normalize_author_list("Foo, N.A., Bar, C. K. "), 'Foo, N; Bar, C')
        self.assertEqual(normalize_author_list("N.A. Foo and C. K. Bar"), 'Foo, N; Bar, C')
        self.assertEqual(normalize_author_list("M. d'Alembert & K.V.U. vanBeuren"), "d'Alembert, M; vanBeuren, K")
        self.assertEqual(normalize_author_list("L. von Beethoven-Tschaikowski et al."), 'von Beethoven-Tschaikowski, L')
        self.assertEqual(normalize_author_list("Abazajian, K. N., Adelman-McCarthy, J. K."), 'Abazajian, K; Adelman-McCarthy, J')
        self.assertEqual(normalize_author_list("Foo, N.A., Bar, C. K. ", initials=False), 'Foo; Bar')
        self.assertEqual(normalize_author_list("N.A. Foo and C. K. Bar", initials=False), 'Foo; Bar')
        self.assertEqual(normalize_author_list("M. de Alembert & K.V.U. vanBeuren", initials=False), 'de Alembert; vanBeuren')
        self.assertEqual(normalize_author_list("L. von Beethoven-Tschaikowski et al.", initials=False), 'von Beethoven-Tschaikowski')
        self.assertEqual(normalize_author_list("Lastname maybe or not", initials=False), "Lastname")
        self.assertEqual(normalize_author_list("lastname maybe or not", initials=False), "lastname maybe or not")

    def test_get_first_author(self):
        """
        Ensure that the return value is the last name of the first author in authorString.
        """
        with self.assertRaises(Exception) as context:
            get_first_author("")
        self.assertTrue('Both leading and trailing found without a majority' in str(context.exception))

        self.assertEqual(get_first_author("Joy, K.-C."), 'Joy')
        self.assertEqual(get_first_author("K.-C. Joy", initials=True), 'Joy, K.-C.')

    def test_get_first_author_last_name(self):
        """
        Ensure that the return value is the last name of the first author of the normalised authors in authors string.
        """
        self.assertEqual(get_first_author_last_name("Foo, Z.-H.; Bar, G."), 'Foo')
        self.assertEqual(get_first_author_last_name(None), None)

    def test_count_matching_authors(self):
        """
        Verifies that statistics returned on the authors matching between ref_authors and ads_authors is correct.
        """
        self.assertEqual(count_matching_authors("Abraham, Z ; Iben, I", ['Abraham, Zulema', 'Iben, Icko, Jr.']),
                         (0, 0, 2, False))
        self.assertEqual(count_matching_authors("Iben, I; Abraham, Z", ['Abraham, Zulema', 'Iben, Icko, Jr.']),
                         (0, 0, 2, False))
        self.assertEqual(count_matching_authors("Abraham, Z", ['Abraham, Zulema', 'Iben, Icko, Jr.']),
                         (1, 0, 1, False))
        self.assertEqual(count_matching_authors("Abraham, Z, Noname", ['Abraham, Zulema', 'Iben, Icko, Jr.']),
                         (1, 1, 1, False))
        self.assertEqual(count_matching_authors("Foobar, K.C.D., Noname", ['Abraham, Zulema', 'Iben, Icko, Jr.']),
                         (2, 2, 0, True))
        self.assertEqual(count_matching_authors("Z. Abraham, I. Iben", ['Abraham, Zulema', 'Iben, Icko, Jr.']),
                         (0, 0, 2, False))
        with self.assertRaises(Exception) as context:
            count_matching_authors("Abraham, Z ; Iben, I", None)
        self.assertTrue('ADS paper without authors -- what should we do?' in str(context.exception))

    def test_add_author_evidence(self):
        """
        Test adding an evidence for ref_authors matching ads_authors.
        """
        # one author match
        evidences = Evidences()
        add_author_evidence(evidences, 'Lefkimmiatis, S.', ['lefkimmiatis, s', 'unser, m'], 'lefkimmiatis, s', False)
        self.assertEqual(evidences['authors'], 0.5)

        # first author missing
        evidences = Evidences()
        add_author_evidence(evidences, 'Lefkimmiatis, S.', ['lefkimmiatis, s', 'unser, m'], 'Foo', False)
        self.assertEqual(evidences['authors'], 0.15)

        # has etal
        evidences = Evidences()
        add_author_evidence(evidences, 'L.Zhong', ['zheng, m', 'chen, w', 'zhang, x', 'liu, x', 'wu, q', 'yu, j'], 'zheng, m', True)
        self.assertEqual(evidences['authors'], 0)

    def test_get_trigrams(self):
        """
        test trigrams present in a_string.
        """
        self.assertEqual(get_trigrams("ab"), [])
        self.assertEqual(get_trigrams("abc"), ['abc'])
        self.assertEqual(get_trigrams("acab aca"), ['aca', 'cab', 'ab ', 'b a', ' ac', 'aca'])

    def test_TrigIndex_lookup(self):
        """
        Test the lookup method which is the index that determine the
        n expansions that have the most trigrams in common with its first
        argument.  It should return a list of these expansions.
        """
        ti = TrigIndex(["abcd", "bcde", "zzy cde"])
        self.assertEqual(ti.lookup("abc cde", 4),
                        [('abcd', 0.6326530612244898), ('bcde', 0.6326530612244898), ('zzy cde', 0.6938775510204082)])
        self.assertEqual(ti.lookup("abc cde", 1),
                         [('zzy cde', 0.6938775510204082)])
        self.assertEqual(ti.lookup("knall", 10), [])

    def test_Trigdict(self):
        """
        Test Trigdic class
        """
        d = Trigdict()
        d["KL"], d["KLOM"], d["KLOM"] = "Short", "Hallo", "Second"
        d["AKLOM"], d["PKLOP"], d["PKLOA"] = "Hillo", "Hullo", "pHullo"
        self.assertEqual(d["KL"], [(1, 'Short')])
        self.assertEqual(d["KLOM"], [(1.0, 'Hallo'), (1.0, 'Second')])
        self.assertEqual(d["PKLOOO"], [(0.7777777777777778, 'Hullo')])
        self.assertEqual(str(d.bestmatches("KLOMA", 3)),
                         "[(0.6799999999999999, 'pHullo'), (0.76, 'Hillo'), (0.88, 'Hallo'), (0.88, 'Second')]")
        self.assertEqual(d.exactmatch("PKLOA"), [(1, 'pHullo')])
        self.assertEqual(d.exactmatch("PKLOOO"), None)
        self.assertEqual(d.values(), set(['Hallo', 'Second', 'Hullo', 'pHullo', 'Hillo']))

    def test_SourceMatcher(self):
        """
        Test the parent class SourceMatcher
        """
        s = SourceMatcher()
        with self.assertRaises(Exception) as context:
            s.exactmatch("A&A")
        self.assertTrue('exactmatch not implemented for this SourceMatcher' in str(context.exception))
        with self.assertRaises(Exception) as context:
            s.bestmatches("A&A", 2)
        self.assertTrue('bestmatches not implemented for this SourceMatcher' in str(context.exception))
        with self.assertRaises(Exception) as context:
            s.is_conf_stem("A&A")
        self.assertTrue('is_conf_stem not implemented for this SourceMatcher' in str(context.exception))
        with self.assertRaises(Exception) as context:
            s["A&A"]
        self.assertTrue('__getitem__ not implemented for this SourceMatcher' in str(context.exception))

    def test_TrigdictSourceMatcher(self):
        """
        Test TrigdictSourceMatcher class
        """
        s = TrigdictSourceMatcher()
        self.assertEqual(s["A&A"][0][0], 1.0)
        self.assertEqual(s["...."], [])
        self.assertEqual(s.is_conf_stem('A&AS.....'), False)
        self.assertEqual(s.is_conf_stem('LPI......'), True)

        # pass in the files
        authority_files = [os.path.abspath(os.path.join(__file__ ,'../../..')) + '/resolver/sourcematcher_dat/' + s
                               for s in ['journals.dat',
                                         'journals_abbrev.dat',
                                         'conferences.dat',
                                         'conferences_abbrev.dat',
                                         'preprints.dat',
                                         'bibstems.dat',
                                         'journals_not_ADS.dat']]
        s = TrigdictSourceMatcher(authority_files)
        self.assertEqual(s.exactmatch("A&A")[0][0], 1.0)
        self.assertEqual(s.exactmatch("Ap J"), None)

    def test_exactmatch(self):
        """
        test exact match, verify that the score is 1.0 if found and if not found should return None
        """
        s = TrigdictSourceMatcher()
        self.assertEqual(s.exactmatch("A&A")[0][0], 1.0)
        self.assertEqual(s.exactmatch("Ap J"), None)

    def test_bestmatches(self):
        """
        test best matches, verify that best matches for Astronomy and Astrophysics Supplement
        includes the following:
        [(0.8977355734112491, 'aard.conf', 'ASTRONOMY AND ASTROPHYSICS RECENT DEVELOPMENTS'),
         (0.9013878743608473, 'A&AS.....', 'ASTRON & ASTROPHYS SUPPLEMENT'),
         (0.912344777209642,  'aap..rept', 'ASTRONOMY AND ASTROPHYSICS PANEL REPORTS'),
         (0.912344777209642,  'aap..rept', 'ASTRONOMY AND ASTROPHYSICS PANEL REPORTS'),
         (0.9196493791088386, 'AASPP....', 'ASTRONONOMY AND ASTROPHYSICS SERIES'),
         (0.9196493791088386, 'AASPP....', 'ASTRONONOMY AND ASTROPHYSICS SERIES'),
         (0.9211102994886778, 'A&ARv....', 'ASTRONOMY AND ASTROPHYSICS REVIEW'),
         (0.9211102994886778, 'A&ARv....', 'ASTRONOMY AND ASTROPHYSICS REVIEW'),
         (0.9211102994886778, 'A&ARv....', 'ASTRONOMY AND ASTROPHYSICS REVIEW'),
         (0.9298758217677137, 'JApAS....', 'JOURNAL OF ASTROPHYSICS AND ASTRONOMY SUPPLEMENT'),
         (0.9517896274653032, 'A&AS.....', 'ASTRON AND ASTROPHYS SUPPLEMENT'),
         (0.9722425127830533, 'ChJAS....', 'CHINESE JOURNAL OF ASTRONOMY AND ASTROPHYSICS SUPPLEMENT'),
         (0.9897735573411249, 'A&AS.....', 'ASTRONOMY AND ASTROPHYSICS SUPPLEMENT SERIES'),
         (0.9897735573411249, 'A&AS.....', 'ASTRONOMY AND ASTROPHYSICS SUPPLEMENT SERIES'),
         (1.0,                'A&AS.....', 'ASTRONOMY AND ASTROPHYSICS SUPPLEMENT')]
        """
        s = TrigdictSourceMatcher()
        best_matches = s.bestmatches("Astronomy and Astrophysics Supplement", 10)
        self.assertTrue(len(list(filter(lambda x: x[1] == 'A&AS.....', best_matches))) > 0)
        self.assertTrue(len(list(filter(lambda x: x[1] == 'ChJAS....', best_matches))) > 0)
        self.assertTrue(len(list(filter(lambda x: x[1] == 'JApAS....', best_matches))) > 0)
        self.assertTrue(len(list(filter(lambda x: x[1] == 'aap..rept', best_matches))) > 0)
        self.assertTrue(len(list(filter(lambda x: x[1] == 'aard.conf', best_matches))) > 0)
        bestmatches = s.bestmatches("Ap J", 3)
        self.assertTrue(len(list(filter(lambda x: x[0] == 1.0 and x[1] == 'ApJ......', bestmatches))) == 1)

    def test_authority_files_errors(self):
        """
        test that if there is any problem in the authority files it is captured
        """
        s = TrigdictSourceMatcher()
        self.assertEqual(s.load_one_source(os.path.dirname(__file__) + '/stubdata/bibstems.dat'), True)
        filename = os.path.dirname(__file__) + '/stubdata/conferences.dat'
        with self.assertRaises(Exception) as context:
            s.load_one_source(filename)
        self.assertTrue('Some entries in %s have errors and were skipped'%(filename) in str(context.exception))
        filename = os.path.dirname(__file__) + '/stubdata/foo.dat'
        with self.assertRaises(Exception) as context:
            s.load_one_source(filename)
        self.assertTrue('%s does not appear to be a source authority file'%(filename) in str(context.exception))

    def test_DeferredSourceMatcher(self):
        """
        test DeferredSourceMatcher class
        """
        sm = DeferredSourceMatcher()
        self.assertEqual(sm.__bases__, (object,))
        self.assertEqual(sm.__name__, 'Unready source matcher')
        self.assertEqual(SOURCE_MATCHER.__name__, 'Unready source matcher')

    def test_Evidences(self):
        """
        test the Evidences class
        """
        e1 = Evidences()
        e1.add_evidence(1, 'bibcode')
        e2 = Evidences()
        e2.add_evidence(0, 'bibcode')
        self.assertEqual(e1 < e2, False)
        self.assertEqual(e1 < None, False)
        self.assertEqual(e1 <= e2, False)
        self.assertEqual(e1 <= None, False)
        self.assertEqual(e1 > e2, True)
        self.assertEqual(e1 > None, False)
        self.assertEqual(e1 >= e2, True)
        self.assertEqual(e1 >= None, False)
        self.assertEqual(e1 == e2, False)
        self.assertEqual(e1 == None, False)
        self.assertEqual(len(e1), 1)
        self.assertEqual(str(e2), 'Evidences(bibcode=0)')
        e2.add_evidence(1, 'year')
        e2.add_evidence(0.5, 'author')
        self.assertEqual(e2.sum(), 1.5)
        e3 = Evidences()
        self.assertEqual(e3.get_score(), 0)
        self.assertEqual(e3.has_veto(), False)
        e3.add_evidence(0, 'bibcode')
        self.assertEqual(e3.has_veto(), True)
        self.assertEqual(e3.single_veto_from('bibcode'), True)
        e3.add_evidence(0, 'year')
        self.assertEqual(e3.single_veto_from('bibcode'), False)
        self.assertEqual(e3.count_votes(), False)
        e4 = Evidences()
        e4.add_evidence(1, 'authors')
        e4.add_evidence(1, 'year')
        e4.add_evidence(1, 'page')
        self.assertEqual(e4.has_veto(), False)
        e4.add_evidence(0, 'pub')
        self.assertEqual(e4.has_veto(), True)
        self.assertEqual(e4.count_votes(), True)
        self.assertEqual(e4['year'], 1)
        self.assertEqual(e1['year'], None)
        self.assertEqual(e1['authors'], None)

    def test_Solution(self):
        """
        test Solution class
        """
        e = Evidences()
        e.add_evidence(1, 'bibcode')
        s = Solution(cited_bibcode='2013SPIE.8004.2013Z', score=e)
        self.assertEqual(str(s), '1.0 2013SPIE.8004.2013Z')
        self.assertEqual(repr(s), "'2013SPIE.8004.2013Z'")

    def test_not_resolved(self):
        """
        test NotResolved exception class
        """
        nr = NotResolved(raw_ref='test reference needs to be long so that we can cut it and show 40 characters only', citing_bibcode=None)
        self.assertEqual(str(nr), 'NOT RESOLVED: test reference needs to be long so that ...')

    def test_no_solution(self):
        """
        test NoSolution exception class
        """
        ns = NoSolution(reason='In Testing Mode')
        self.assertEqual(str(ns), 'In Testing Mode')
        ns = NoSolution(reason='In Testing Mode', ref='test reference')
        self.assertEqual(str(ns),'In Testing Mode: test reference')

    def test_make_solr_condition(self):
        """
        test rearranging authors for solr query
        """
        self.assertEqual(make_solr_condition("title", "Far: From here to there (and back)"),
                         'title:(Far AND From AND here AND \\to AND there AND \\and AND back)')
        self.assertEqual(make_solr_condition("title~", "Meteorological Journal Kept Apartments Royal Society"),
                         'title:"Meteorological Journal Kept Apartments Royal Society"~')
        self.assertEqual(make_solr_condition("title", ""), None)
        self.assertEqual(make_solr_condition("author", "B. Traven and D. d'Vaucouleurs"),
                         'author:("Traven, B" AND "d\'Vaucouleurs, D")')
        self.assertEqual(make_solr_condition("first_author_norm~", "frisken gibson, s"),
                         'first_author:"frisken gibson"~')
        self.assertEqual(make_solr_condition("arxiv", "1904.07238"), 'identifier:("arxiv:1904.07238")')
        self.assertEqual(make_solr_condition("ascl", "1906.010"), 'identifier:("ascl:1906.010")')
        self.assertEqual(make_solr_condition("doi","10.1364/JOSAA.9.000154"), 'doi:"10.1364/JOSAA.9.000154"')
        # self.assertEqual(make_solr_condition("page", "154"), 'page:("?54" or "1?4" or "15?")')
        # for now since wildcard ? has been turned off when preceding any character, use this expanded version
        page_query = '"a54" or "b54" or "c54" or "d54" or "e54" or "f54" or "g54" or "h54" or "i54" or "j54" or ' \
                     '"k54" or "l54" or "m54" or "n54" or "o54" or "p54" or "q54" or "r54" or "s54" or "t54" or ' \
                     '"u54" or "v54" or "w54" or "x54" or "y54" or "z54" or "054" or "154" or "254" or "354" or ' \
                     '"454" or "554" or "654" or "754" or "854" or "954" or "1?4" or "15?"'
        self.assertEqual(make_solr_condition("page", "154"), 'page:(%s)'%page_query)
        self.assertEqual(make_solr_condition("bibstem", "JOSAA"), 'bibstem:(JOSAA)')
        self.assertEqual(make_solr_condition("year", "1992"), 'year:"1992"')
        self.assertEqual(make_solr_condition("year~", "1992"), 'year:[1987 TO 1997]')

    def test_solve_reference(self):
        """
        testing solve_reference with various fields
        """
        # testing with author, title, year, volume, and page
        ref = {'title': "The NASA Astrophysics Data System's Decadal Plan for the 2020s",
               'authors': 'Accomazzi, A.',
               'volume': '233',
               'year': '2019',
               'page': '207.04'}
        self.assertEqual(str(solve_reference(Hypotheses(ref))), '1.0 2019AAS...23320704A')
        # testing with first author only and page
        # eventhough other authors are missing but because of page match is found
        ref = {'authors': 'Accomazzi, A.',
               'journal': 'AAS233 Meeting',
               'volume': '233',
               'year': '2019',
               'page': '381.08'}
        self.assertEqual(str(solve_reference(Hypotheses(ref))), '0.8 2019AAS...23338108A')
        # testing with first author only and no page, hence record with only the first author is returned
        ref = {'authors': 'Accomazzi, A.',
               'journal': 'AAS233 Meeting',
               'volume': '233',
               'year': '2019',
               'page': '0'}
        self.assertEqual(str(solve_reference(Hypotheses(ref))), '0.8 2019AAS...23320704A')
        # when we have multiple solutions and not enough reference information to decide which
        # page and author are the deciding factor between these two test records
        # here first author and page are wrong
        ref = {'authors': 'Acomazi, A., et al',
               'volume': '233',
               'year': '2019',
               'page': '0'}
        with self.assertRaises(Exception) as context:
            solve_reference(Hypotheses(ref))
        self.assertTrue('Hypotheses exhausted' in str(context.exception))
        # when journal, volume, and year match
        ref = {'authors': 'Accomazzi, A., et al',
               'journal': 'AAS233 Meeting',
               'volume': '233',
               'year': '2019',
               'page': '0',
               'refstr': 'Accomazzi, A., et al., 2019. AAS233 Meeting 233'}
        # note that the title is from the first record of test data and authors from the second record,
        # however the first record is authored by one author only and
        # it is the same first author of the second record
        # verify that the first record is returned
        self.assertEqual(str(solve_reference(Hypotheses(ref))), '0.8 2019AAS...23320704A')

    def test_add_volume_evidence(self):
        """
        test add_volume_evidence
        """
        # both reference and ads missing volume values
        self.assertEqual(add_volume_evidence(Evidences(), None, None, None, None), None)
        self.assertEqual(add_volume_evidence(Evidences(), '', '', '', ''), None)
        # when one is missing
        evidences = Evidences()
        self.assertEqual(add_volume_evidence(evidences, '233', '', '', ''), None)
        self.assertEqual(evidences.get_score(), 0)
        evidences = Evidences()
        self.assertEqual(add_volume_evidence(evidences, '', '233', '', ''), None)
        self.assertEqual(evidences.get_score(), -1)
        # when matched
        evidences = Evidences()
        self.assertEqual(add_volume_evidence(evidences, '233', '233', '', ''), None)
        self.assertEqual(evidences.get_score(), 1)
        # when unmatched
        evidences = Evidences()
        self.assertEqual(add_volume_evidence(evidences, '223', '233', '', ''), None)
        self.assertEqual(evidences.get_score(), 0.7)
        # when not integer, but matched
        evidences = Evidences()
        self.assertEqual(add_volume_evidence(evidences, '233-3', '233-3', '', ''), None)
        self.assertEqual(evidences.get_score(), 1)
        # when not integer, unmatched
        evidences = Evidences()
        self.assertEqual(add_volume_evidence(evidences, '223-3', '233-3', '', ''), None)
        self.assertEqual(evidences.get_score(), 0)
        # when volume is year and there is an issue
        evidences = Evidences()
        self.assertEqual(add_volume_evidence(evidences, '233', '2018', '233', ''), None)
        self.assertEqual(evidences.get_score(), 1)

    def test_clean_ads_page(self):
        """
        test clean_ads_page
        """
        self.assertEqual(clean_ads_page('32B'), '32')
        self.assertEqual(clean_ads_page('207.04'), '207.04')
        self.assertEqual(clean_ads_page('33-45'), '33')
        self.assertEqual(clean_ads_page('IV92-IV99'), 'IV92-IV99')

    def test_compute_page_delta(self):
        """
        test compute_page_delta
        """
        self.assertEqual(compute_page_delta("23", "23"), 1)
        self.assertEqual(compute_page_delta("21", "234"), 0)
        self.assertEqual(compute_page_delta("32", "L32", "L"), 1)
        self.assertEqual(compute_page_delta("32", "L32", "P"), 1 + self.current_app.config['NO_LETTER_DEMERIT'])
        self.assertEqual(compute_page_delta("32", "32B"), 1 + self.current_app.config['NO_LETTER_DEMERIT'])
        self.assertEqual(compute_page_delta("A32", "32"), 1 + self.current_app.config['NO_LETTER_DEMERIT'])
        self.assertEqual(compute_page_delta("", ""), None)
        self.assertEqual(compute_page_delta("23", None), 0)
        self.assertEqual(compute_page_delta(":M20", "23"), 0)
        self.assertEqual(compute_page_delta(":M20", ":M20"), 1)
        self.assertEqual(compute_page_delta("233", "23"), 0)
        self.assertEqual(compute_page_delta("23", "0"), 0)

    def test_add_page_evidence(self):
        """
        test add_page_evidence
        """
        self.assertEqual(add_page_evidence(Evidences(), None, None), None)
        self.assertEqual(add_page_evidence(Evidences(), 23, 0), None)

    def test_compute_pubstring_statistics(self):
        """
        test compute_pubstring_statistics
        """
        self.assertEqual(compute_pubstring_statistics("A&A", "Astronomy and Astrophysics", "A&A"), (1, 0))
        self.assertEqual(compute_pubstring_statistics("A&AS", "Astronomy and Astrophysics", "A&A"), (1, 1))

    def test_string_similarity(self):
        """
        test string_similarity
        """
        self.assertEqual(string_similarity(None, None), -1)
        self.assertEqual(string_similarity('', ''), -1)
        self.assertTrue(string_similarity('The NASA Astrophysics Data System’s Decadal Plan for the 2020s',
                                          'Transitioning from ADS Classic to the new ADS search platform')
                        < 0.15)

    def test_add_publication_evidence(self):
        """
        test add_publication_evidence
        """
        evidences = Evidences()
        add_publication_evidence(evidences,
                                 'The NASA Astrophysics Data System’s Decadal Plan for the 2020s',
                                 'AAS',
                                 '',
                                 'The NASA Astrophysics Data System’s Decadal Plan for the 2020s',
                                 '2019AAS...23320704A',
                                 'AAS')
        self.assertEqual(evidences.get_score(), 1)
        evidences = Evidences()
        add_publication_evidence(evidences,
                                 'Nucl. Instrum. Methods Phys. Res. A',
                                 '',
                                 '',
                                 'Nuclear Instruments and Methods in Physics Research A',
                                 '1997NIMPA.389...81B',
                                 'NIMPA')
        self.assertEqual(evidences.get_score(), 0.6)
        evidences = Evidences()
        add_publication_evidence(evidences,
                                 'The NASA Astrophysics Data System’s Decadal Plan for the 2020s',
                                 '',
                                 '',
                                 '',
                                 '2019AAS...23320704A',
                                 'AAS')
        self.assertEqual(evidences.get_score(), -1)
        evidences = Evidences()
        add_publication_evidence(evidences,
                                 '',
                                 '',
                                 '',
                                 'Nuclear Instruments and Methods in Physics Research A',
                                 '1997NIMPA.389...81B',
                                 'NIMPA')
        self.assertEqual(evidences.get_score(), 0)
        # when there is an error in reference, the author is not parsed properly,
        # and hence journal is not identified correctly, if ads bibstem is in ref_str, do not penalize
        evidences = Evidences()
        add_publication_evidence(evidences,
                                 'iaz',
                                 '',
                                 'Simon-D iaz, S., Castro, N., Garc ia, M., & Herrero, A. 2011a, in IAUS, Vol. 272, 310-312',
                                 'Active OB Stars: Structure, Evolution, Mass Loss, and Critical Limits',
                                 '2011IAUS..272..310S',
                                 'IAUS')
        self.assertEqual(evidences.get_score(), 0)
        evidences = Evidences()
        add_publication_evidence(evidences, '', '', '', '', '', '')
        self.assertEqual(evidences.get_score(), 0)

    def test_has_word(self):
        """
        test has_word
        """
        self.assertEqual(has_word("Foo, 23, 123", "1"), False)
        self.assertEqual(has_word("Foo, 23, 123", "Foo"), True)
        self.assertEqual(has_word("Foo, 23, 123", "23"), True)
        self.assertEqual(has_word("Foo, 23, 123", "123"), True)

    def test_has_thesis_indicators(self):
        """
        test has_thesis_indicators
        """
        self.assertEqual(has_thesis_indicators(u"2007b, PhD thesis , Cornell"), True)
        self.assertEqual(has_thesis_indicators(u"Astrophdical Journal"), False)
        self.assertEqual(has_thesis_indicators(u"CORNELL UNIVERSITY, 1969. Dissertation Abstracts International, Volume: 30-07, Section: B, page: 3319."), True)
        #self.assertEqual(0, 1)

    def test_cook_title_string(self):
        """
        test cook_title_string
        """
        self.assertEqual(cook_title_string("Untimely results in atomic spec."), 'Untimely results atomic')
        self.assertEqual(cook_title_string("a b c, a cat was in the snow"), '')

    def test_Querier(self):
        solrquery = Querier()
        self.assertEqual(solrquery.make_params('author:("Accomazzi, A") AND year:"2019" AND bibstem:(AAS)'),
                         {'q': 'author:("Accomazzi, A") AND year:"2019" AND bibstem:(AAS)',
                          'rows': '100',
                          'fl': u'author,[fields author=10]author_norm,[fields author_norm=10],first_author_norm,year,title,pub,pub_raw,aff_raw,[fields aff_raw=1],volume,issue,page,page_range,bibstem,bibcode,identifier,doi,doctype'})

        # no author_norm
        solution = {u'bibcode': u'2013JARS....7.3461V',
                    u'author': [u'Vasuki, Perumal', u'Mohamed Mansoor Roomi, S.'],
                    u'title': [u'Particle swarm optimization-based despeckling and decluttering of wavelet packet transformed synthetic aperture radar images'],
                    u'doctype': u'article', u'pub': u'Journal of Applied Remote Sensing',
                    u'pub_raw': u'Journal of Applied Remote Sensing, Volume 7, id. 073461 (2013).',
                    u'volume': u'7',
                    u'year': u'2013',
                    u'page': [u'073461']}
        self.assertEqual(solrquery.massage_solution(solution),
                         {u'pub': u'Journal of Applied Remote Sensing', u'volume': u'7',
                          'author_norm': ['Vasuki, Perumal', 'Mohamed Mansoor Roomi, S.'], u'year': u'2013',
                          'first_author_norm': 'vasuki, perumal', u'bibcode': u'2013JARS....7.3461V',
                          u'author': [u'Vasuki, Perumal', u'Mohamed Mansoor Roomi, S.'],
                          u'title': u'Particle swarm optimization-based despeckling and decluttering of wavelet packet transformed synthetic aperture radar images',
                          u'doctype': u'article',
                          u'pub_raw': u'Journal of Applied Remote Sensing, Volume 7, id. 073461 (2013).',
                          u'page': u'073461'})

class TestResolverHypotheses(TestCase):

    def create_app(self):
        self.current_app = app.create_app(**{
            'REFERENCE_SERVICE_LIVE': False
           })
        return self.current_app

    def setUp(self):
        """
        load the necessary objects
        """
        self.current_app.extensions['source_matcher'] = load_source_matcher()

    def tearDown(self):
        """
        cleanup
        """
        self.current_app.extensions['source_matcher'] = None

    def test_a_Hypothesis(self):
        """
        test Hypothesis class
        """
        h = Hypothesis(name="test_arxiv_id", hints={'arxiv':'1905.07407'},
                       get_score_function=get_score_for_reference_identifier, input_fields={'arxiv':'1905.07407'})
        s = h.get_score({'identifier':['arXiv:1905.07407'], 'bibcode': '2019arXiv190507407S'}, h)
        self.assertEqual(s['bibcode'], 1)
        self.assertEqual(h.get_detail('has_etal'), None)

    def test_get_score_for_input_fields(self):
        """
        test scoring function get_score_for_input_fields
        """
        result_record= {u'bibcode': u'1992JOSAA...9..154F',
                        u'author': [u'Frisken Gibson, Sarah', u'Lanni, Frederick'],
                        u'title': u'Experimental test of an analytical model of aberration in an oil-immersion objective lens used in three-dimensional light microscopy',
                        u'doctype': u'article',
                        u'pub': u'Journal of the Optical Society of America A',
                        u'pub_raw': u'Journal of the Optical Society of America A, vol. 9, issue 1, p. 154',
                        u'volume': u'9',
                        u'author_norm': ['frisken gibson, s', 'lanni, f'],
                        u'year': u'1992',
                        u'first_author_norm': 'frisken gibson, s',
                        u'identifier': [u'1992JOSAA...9..154F', u'10.1364/JOSAA.9.000154', u'10.1364/JOSAA.9.000154'],
                        u'page': u'154'}
        input_fields= {'volume': u'9',
                       'year': u'1992',
                       'pub': u'J. Opt. Soc. Am. A',
                       'author': u'S.  Frisken-Gibson,F.  Lanni'}
        hypothesis = Hypothesis("testing", {
                            "author": input_fields["author"],
                            "bibstem": get_best_bibstem_for(input_fields["pub"]),
                            "year": input_fields["year"],
                            "volume": input_fields["volume"],
                            "pub": input_fields["pub"]},
                            get_score_for_input_fields,
                       input_fields=input_fields,
                       has_etal=False)
        evidences = get_score_for_input_fields(result_record, hypothesis)
        # matches are authors, year, pub, and volume
        self.assertEqual(evidences.get_score(), 4.0)

    def test_inspect_doubtful_solutions(self):
        """
        test doubtful solutions, when there is more than one possible solution without a doubt (i.e., all fields have
        in evidences have positive values
        :return:
        """
        e1 = Evidences()
        e1.add_evidence(0.11, 'authors')
        e1.add_evidence(0.15, 'year')
        e2 = Evidences()
        e2.add_evidence(0.05, 'authors')
        e2.add_evidence(0.21, 'year')
        e3 = Evidences()
        e3.add_evidence(0.05, 'authors')
        e3.add_evidence(0.21, 'year')
        e3.add_evidence(-1, 'page')

        input_fields = {u'bibcode': u'1992JOSAA...9..154F',
                        u'author': [u'Frisken Gibson, Sarah', u'Lanni, Frederick'],
                        u'year': u'1992'}
        hypothesis = Hypothesis("testing-fielded-author/year", {
                            "author": input_fields["author"],
                            "year": input_fields["year"]},
                       get_score_for_input_fields,
                       input_fields=input_fields,
                       has_etal=False)

        with self.assertRaises(Exception) as context:
            inspect_doubtful_solutions(scored_solutions=[(e1, {u'bibcode': u'1992JOSAA...9..154F'})],
                                       query_string='the_query', hypothesis=hypothesis)
        self.assertTrue('Try again if desperate' in str(context.exception))
        with self.assertRaises(Exception) as context:
            inspect_doubtful_solutions(scored_solutions=[(e1, {u'bibcode': u'1992JOSAA...9..154F'}),(e2, {u'bibcode': u'1992JOSAA...9..154F'})],
                                       query_string='the_query', hypothesis=hypothesis)
        self.assertEqual('No unique non-vetoed doubtful solution: the_query', str(context.exception))
        with self.assertRaises(Exception) as context:
            inspect_doubtful_solutions(scored_solutions=[(e3, {u'bibcode': u'1992JOSAA...9..154F'})],
                                       query_string='the_query', hypothesis=hypothesis)
        self.assertTrue('Try again if desperate' in str(context.exception))

    def test_inspect_ambiguous_solutions(self):
        """
        test inspect_ambiguous_solutions
        """
        e1 = Evidences()
        e1.add_evidence(0.11, 'authors')
        e1.add_evidence(0.15, 'year')
        e2 = Evidences()
        e2.add_evidence(0.05, 'authors')
        e2.add_evidence(0.21, 'year')
        e2.add_evidence(0.1, 'volume')
        e3 = Evidences()
        e3.add_evidence(0.05, 'authors')
        e3.add_evidence(0.21, 'year')
        e3.add_evidence(-1, 'page')
        e4 = Evidences()
        e4.add_evidence(0.05, 'authors')
        e4.add_evidence(0.21, 'year')

        input_fields = {u'bibcode': u'1992JOSAA...9..154F',
                        u'author': [u'Frisken Gibson, Sarah', u'Lanni, Frederick'],
                        u'year': u'1992',
                        u'volume': u'9'}
        hypothesis = Hypothesis("testing-fielded-author/year", {
                            "author": input_fields["author"],
                            "year": input_fields["year"]},
                       get_score_for_input_fields,
                       input_fields=input_fields,
                       has_etal=False)
        scored_solutions = [(e1, {u'bibcode': u'1992JOSAA...9..154F'})]
        self.assertEqual(inspect_ambiguous_solutions(scored_solutions=scored_solutions,
                                        query_string='the_query', hypothesis=hypothesis),
                         scored_solutions[0])
        with self.assertRaises(Exception) as context:
            inspect_ambiguous_solutions(scored_solutions=[(e3, {u'bibcode': u'1992JOSAA...9..154F'})],
                                        query_string='the_query', hypothesis=hypothesis)
        self.assertTrue('Try again if desperate' in str(context.exception))
        scored_solutions = [(e1, {u'bibcode': u'1992JOSAA...9..154F'}), (e2, {u'bibcode': u'1992JOSAA...9..154F'})]
        self.assertEqual(inspect_ambiguous_solutions(scored_solutions=scored_solutions,
                                        query_string='the_query', hypothesis=hypothesis),
                         scored_solutions[1])
        e1.add_evidence(0.05, 'title')
        e4.add_evidence(0.05, 'title')
        scored_solutions = [(e1, {u'bibcode': u'1992JOSAA...9..154F', u'title': u'Experimental test of an analytical model of aberration in an oil-immersion objective lens used in three-dimensional light microscopy', u'year': u'1992'}),
                            (e4, {u'bibcode': u'1992JOSAA...9..154F', u'title': u'Experimental test of an analytical model of aberration in an oil-immersion objective lens used in three-dimensional light microscopy'})]
        self.assertEqual(inspect_ambiguous_solutions(scored_solutions=scored_solutions,
                                        query_string='the_query', hypothesis=hypothesis),
                         scored_solutions[1])
        scored_solutions = [(e1, {u'bibcode': u'1992JOSAA...9..154F', u'title': u'title1 Experimental test of an analytical model of aberration in an oil-immersion objective lens used in three-dimensional light microscopy', u'year': u'1992'}),
                            (e4, {u'bibcode': u'1992JOSAA...9..154F', u'title': u'title2 Experimental test of an analytical model of aberration in an oil-immersion objective lens used in three-dimensional light microscopy'})]
        with self.assertRaises(Exception) as context:
            inspect_ambiguous_solutions(scored_solutions=scored_solutions,
                                        query_string='the_query', hypothesis=hypothesis)
        self.assertTrue('Ambiguous the_query.' in str(context.exception))

    def test_choose_solution(self):
        """

        """
        e1 = Evidences()
        e1.add_evidence(0.0, 'authors')
        e1.add_evidence(0.3, 'year')
        e1.add_evidence(0, 'page')
        e1.add_evidence(-0.6, 'pubstring')
        e1.add_evidence(0, 'volume')
        e2 = Evidences()
        e2.add_evidence(1.0, 'authors')
        e2.add_evidence(1.0, 'year')
        e2.add_evidence(0, 'page')
        e2.add_evidence(0.6, 'pubstring')
        e2.add_evidence(1, 'volume')
        e3 = Evidences()
        e3.add_evidence(1.0, 'authors')
        e3.add_evidence(1.0, 'year')
        e3.add_evidence(1.0, 'page')
        e3.add_evidence(0.8, 'pubstring')
        e3.add_evidence(0.8, 'volume')

        solution = {u'bibcode': u'2013JARS....7.3461V',
                    u'author': [u'Vasuki, Perumal', u'Mohamed Mansoor Roomi, S.'],
                    u'title': u'Particle swarm optimization-based despeckling and decluttering of wavelet packet transformed synthetic aperture radar images',
                    u'doctype': u'article', u'pub': u'Journal of Applied Remote Sensing',
                    u'pub_raw': u'Journal of Applied Remote Sensing, Volume 7, id. 073461 (2013).',
                    u'volume': u'7', u'author_norm': ['vasuki, p', 'mohamed mansoor roomi, s'], u'year': u'2013',
                    u'first_author_norm': 'vasuki, p',
                    u'identifier': [u'2013JARS....7.3461V', u'10.1117/1.JRS.7.073461', u'10.1117/1.JRS.7.073461'],
                    u'page': u'073461'}

        hypothesis = Hypothesis("testing-fielded-author/year", {
                                    "author": solution["author"],
                                    "year": solution["year"]},
                                get_score_for_input_fields,
                                input_fields=solution,
                                has_etal=False)

        with self.assertRaises(Exception) as context:
            choose_solution(candidates=[], query_string='the_query', hypothesis=hypothesis)
        self.assertTrue('Not even a doubtful solution' in str(context.exception))
        with self.assertRaises(Exception) as context:
            choose_solution(candidates=[(e1, solution)], query_string='the_query', hypothesis=hypothesis)
        self.assertEqual('No unique non-vetoed doubtful solution: the_query', str(context.exception))
        candidates = [(e2, solution)]
        self.assertTrue(choose_solution(candidates=candidates, query_string='the_query', hypothesis=hypothesis),
                        candidates[0])
        with self.assertRaises(Exception) as context:
            choose_solution(candidates=[(e2, solution), (e2, solution)], query_string='the_query', hypothesis=hypothesis)
        self.assertTrue('2 solutions with equal (good) score.' in str(context.exception))
        candidates = [(e2, solution), (e3, solution)]
        self.assertTrue(choose_solution(candidates=candidates, query_string='the_query', hypothesis=hypothesis),
                        candidates[0])

    def test_get_score_for_reference_identifier(self):
        """
        test get_score_for_reference_identifier
        """
        # reference is DOI
        solution = {u"bibcode": u"2019NatNa..14...89C",
                    u"doi":[u"10.1038/s41565-018-0319-4"]}

        ref = {"doi":"10.1038/s41565-018-0319-4"}
        hypothesis = Hypothesis("testing-fielded-DOI", {
                                    "doi": ref["doi"]},
                                get_score_for_reference_identifier,
                                input_fields=ref)
        self.assertEqual(get_score_for_reference_identifier(solution, hypothesis).get_score(), 1)

        # if it does not match
        ref = {"doi":"no match"}
        hypothesis = Hypothesis("testing-fielded-DOI", {
                                    "doi": ref["doi"]},
                                get_score_for_reference_identifier,
                                input_fields=ref)
        self.assertEqual(get_score_for_reference_identifier(solution, hypothesis).get_score(), -1)

        # reference is arxiv id which is available in eid in solr
        solution = {u"bibcode": u"2019arXiv190501258L",
                    u"identifier": [u"arXiv:1905.01258"]}

        ref = {"arxiv":"1905.01258"}
        hypothesis = Hypothesis("testing-fielded-arxiv", {
                                    "arxiv": ref["arxiv"]},
                                get_score_for_reference_identifier,
                                input_fields=ref)
        self.assertEqual(get_score_for_reference_identifier(solution, hypothesis).get_score(), 1)

        # if it does not match
        ref = {"arxiv":"no match"}
        hypothesis = Hypothesis("testing-fielded-arxiv", {
                                    "arxiv": ref["arxiv"]},
                                get_score_for_reference_identifier,
                                input_fields=ref)
        self.assertEqual(get_score_for_reference_identifier(solution, hypothesis).get_score(), -1)

    def test_get_book_score_for_input_fields(self):
        """
        test get_book_score_for_input_fields
        """
        solution = {
            u"doctype":u"book",
            u"year":u"2019",
            u"bibcode":u"2019msme.book.....R",
            u"bibstem":u"msme",
            u"identifier":[u"2019msme.book.....R"],
            u"pub_raw":u"Meteoroids: Sources of Meteors on Earth and Beyond. Editors: Galina O. Ryabova, David J. Asher and Margaret D. Campbell-Brown. ISBN 9781108426718. Cambridge University Press, 2019",
            u"pub":u"Meteoroids: Sources of Meteors on Earth and Beyond. Editors: Galina O. Ryabova",
            u"first_author_norm":u"Ryabova, G",
            u"author":[u"Ryabova, Galina O.", u"Asher, David J.", u"Campbell-Brown, Margaret J."],
            u"title":u"Meteoroids: Sources of Meteors on Earth and Beyond",
            u"author_norm":["Ryabova, G", "Asher, D", "Campbell-Brown, M"]
        }
        # note passing in a mistaken year by a character
        ref = {"authors": "Ryabova, G., Asher, D., Campbell Brown, M.",
               "title": "Meteoroids: Sources of Meteors on Earth and Beyond",
               "year": "2009"}
        normalized_authors = normalize_author_list(ref["authors"], initials=True)
        # note that specifying hints here is useless since we are passing the solution in already
        # put it here to know what information was used in the query corresponding to the scare function called
        hypothesis = Hypothesis("test-fielded-book-title", {
                           "author": normalized_authors,
                            "title": ref["title"],
                            "year": ref["year"]},
                        get_book_score_for_input_fields,
                        input_fields=ref,
                        page_qualifier=ref.get("qualifier"),
                        has_etal=False,
                        normalized_authors=normalized_authors)
        # Evidences(authors=1, year=0.75, doctype=1, pubstring=1.0)
        self.assertEqual(get_book_score_for_input_fields(solution, hypothesis).get_score(), 3.75)

    def test_get_thesis_score_for_input_fields(self):
        """
        test get_thesis_score_for_input_fields
        """
        solution = {
            u"first_author_norm": u"Rowden, P",
            u"year":u"2019",
            u"bibcode":u"2019PhDT........11R",
            u"identifier":[u"2019PhDT........11R"],
            u"author":[u"Rowden, Pamela M."],
            u"pub":u"Ph.D. Thesis",
            u"doctype":u"phdthesis",
            u"pub_raw":u"PhD These, The Open University, 2019",
            u"title":u"False Positives and Shallow Eclipsing Binaries in Transiting Exoplanet Surveys",
            u"author_norm":[u"Rowden, P"],
            u"aff_raw": [u"The Open University"]
        }
        ref = {"authors": "Rowden, P.", "year": "2019", "refstr": "PhD These, The Open University, 2019"}
        # note that specifying hints here is useless since we are passing the solution in already
        # put it here to know what information was used in the query corresponding to the scare function called
        normalized_authors = normalize_author_list(ref["authors"], initials=True)
        hypothesis = Hypothesis("test-fielded-thesis", {
                            "author": normalized_authors,
                            "pub_escaped": "(%s)"%" or ".join(self.current_app.config["THESIS_INDICATOR_WORDS"]),
                            "year": ref["year"]},
                        get_thesis_score_for_input_fields,
                        input_fields=ref,
                        normalized_authors=normalized_authors)
        # Evidences(doctype=1, author=1.0, year=1.0, affiliation=1.0)
        self.assertEqual(get_thesis_score_for_input_fields(solution, hypothesis).get_score(), 4)

        # wrong initial
        ref = {"authors": "Rowden, R.", "year": "2019", "refstr": "PhD These, The Open University, 2019"}
        # note that specifying hints here is useless since we are passing the solution in already
        # put it here to know what information was used in the query corresponding to the scare function called
        normalized_authors = normalize_author_list(ref["authors"], initials=True)
        hypothesis = Hypothesis("test-fielded-thesis", {
                            "author": normalized_authors,
                            "pub_escaped": "(%s)"%" or ".join(self.current_app.config["THESIS_INDICATOR_WORDS"]),
                            "year": ref["year"]},
                        get_thesis_score_for_input_fields,
                        input_fields=ref,
                        normalized_authors=normalized_authors)
        # Evidences(doctype=1, author=0.7, year=1.0, affiliation=1.0)
        self.assertEqual(get_thesis_score_for_input_fields(solution, hypothesis).get_score(), 3.7)

        # mistaken year
        ref = {"authors": "Rowden, P.", "year": "2018", "refstr": "PhD These, The Open University, 2019"}
        normalized_authors = normalize_author_list(ref["authors"], initials=True)
        hypothesis = Hypothesis("test-fielded-thesis", {
                            "author": normalized_authors,
                            "pub_escaped": "(%s)"%" or ".join(self.current_app.config["THESIS_INDICATOR_WORDS"]),
                            "year": ref["year"]},
                        get_thesis_score_for_input_fields,
                        input_fields=ref,
                        normalized_authors=normalized_authors)
        # Evidences(doctype=1, author=1.0, year=0.75, affiliation=1.0)
        self.assertEqual(get_thesis_score_for_input_fields(solution, hypothesis).get_score(), 3.75)

        # no thesis indication
        solution = {
            u"first_author_norm": u"Rowden, P",
            u"year": u"2019",
            u"bibcode": u"2019PhDT........11R",
            u"identifier":[u"2019PhDT........11R"],
            u"author":[u"Rowden, Pamela M."],
            u"pub": u"Ph.D. Thesis",
            u"doctype": u"phdthesis",
            u"pub_raw": u"no indicator, The Open University, 2019",
            u"title":u"False Positives and Shallow Eclipsing Binaries in Transiting Exoplanet Surveys",
            u"author_norm":[u"Rowden, P"],
            u"aff_raw": [u"The Open University"]
        }
        ref = {"authors": "Rowden, P.", "year": "2019", "refstr": "PhD These, The Open University, 2019"}
        hypothesis = Hypothesis("test-fielded-thesis", {
                            "author": normalized_authors,
                            "pub_escaped": "(%s)"%" or ".join(self.current_app.config["THESIS_INDICATOR_WORDS"]),
                            "year": ref["year"]},
                        get_thesis_score_for_input_fields,
                        input_fields=ref,
                        normalized_authors=normalized_authors)
        # Evidences(doctype=1, author=1.0, year=1.0, affiliation=1.0)
        self.assertEqual(get_thesis_score_for_input_fields(solution, hypothesis).get_score(), 4)

        # if solution contians multiple authors, penalize
        solution = {
            u"first_author_norm": u"Rowden, P",
            u"year": u"2019",
            u"bibcode": u"2019PhDT........11R",
            u"identifier":[u"2019PhDT........11R"],
            u"author":[u"Rowden, Pamela M.", u"Grady, M. M."],
            u"pub": u"Ph.D. Thesis",
            u"doctype": u"phdthesis",
            u"pub_raw": u"PhD These, The Open University, 2019",
            u"title":u"False Positives and Shallow Eclipsing Binaries in Transiting Exoplanet Surveys",
            u"author_norm":[u"Rowden, P", u"Grady, M"],
            u"aff_raw": [u"The Open University"]
        }
        # Evidences(doctype=1, author=-1, year=1.0, affiliation=1.0)
        self.assertEqual(get_thesis_score_for_input_fields(solution, hypothesis).get_score(), 2.0)

        # if no aff_raw
        solution = {
            u"first_author_norm": u"Rowden, P",
            u"year": u"2019",
            u"bibcode": u"2019PhDT........11R",
            u"identifier":[u"2019PhDT........11R"],
            u"author":[u"Rowden, Pamela M.", u"Grady, M. M."],
            u"pub": u"Ph.D. Thesis",
            u"doctype": u"phdthesis",
            u"pub_raw": u"PhD These, The Open University, 2019",
            u"title":u"False Positives and Shallow Eclipsing Binaries in Transiting Exoplanet Surveys",
            u"author_norm":[u"Rowden, P", u"Grady, M"],
            u"aff_raw": [u"-"]
        }
        # Evidences(doctype=1, author=-1, year=1.0, affiliation=0)
        self.assertEqual(get_thesis_score_for_input_fields(solution, hypothesis).get_score(), 1.0)

    def test_add_publication_evidence_error(self):
        """
        test add_publication_evidence for when there is a typo in the reference journal
        """
        solution = {u'bibcode': u'2018AJ....156..102S',
                    u'author': [u'Stassun, Keivan G.', u'Oelkers, Ryan J.', u'Pepper, Joshua', u'Paegert, Martin', u'De Lee, Nathan', u'Torres, Guillermo', u'Latham, David W.', u'Charpinet, St\xe9phane', u'Dressing, Courtney D.', u'Huber, Daniel', u'Kane, Stephen R.', u'L\xe9pine, S\xe9bastien', u'Mann, Andrew', u'Muirhead, Philip S.', u'Rojas-Ayala, B\xe1rbara', u'Silvotti, Roberto', u'Fleming, Scott W.', u'Levine, Al', u'Plavchan, Peter'],
                    u'bibstem': u'AJ',
                    u'doctype': u'article',
                    u'pub': u'The Astronomical Journal',
                    u'pub_raw': u'The Astronomical Journal, Volume 156, Issue 3, article id. 102, <NUMPAGES>39</NUMPAGES> pp. (2018).',
                    u'volume': u'156',
                    u'doi': [u'10.3847/1538-3881/aad050'],
                    u'author_norm': ['stassun, k', 'oelkers, r', 'pepper, j', 'paegert, m', 'de lee, n', 'torres, g', 'latham, d', 'charpinet, s', 'dressing, c', 'huber, d', 'kane, s', 'lepine, s', 'mann, a', 'muirhead, p', 'rojas ayala, b', 'silvotti, r', 'fleming, s', 'levine, a', 'plavchan, p'],
                    u'year': u'2018',
                    u'first_author_norm': 'stassun, k',
                    u'title': u'The TESS Input Catalog and Candidate Target List',
                    u'identifier': [u'2017arXiv170600495S', u'2018AJ....156..102S', u'10.3847/1538-3881/aad050', u'2017arXiv170600495S', u'arXiv:1706.00495', u'10.3847/1538-3881/aad050'],
                    u'issue': u'3',
                    u'page': u'102'}
        # note that journal was supposed to be AJ
        ref = {'journal': u'ApJ',
               'authors': u'Stassun, K. G., Oelkers, R. J., Pepper, J., et al.',
               'refstr': u'Stassun, K. G., Oelkers, R. J., Pepper, J., et al. 2018, ApJ, 156, 102',
               'volume': u'156',
               'year': u'2018',
               'page': u'102'}
        normalized_authors = normalize_author_list(ref["authors"], initials=True)
        hypothesis = Hypothesis("testing-fielded-author/year/volume/page", {
                            "author": normalized_authors,
                            "year": ref["year"],
                            "volume": ref["volume"],
                            "page": ref["page"]},
                        get_score_for_input_fields,
                        input_fields=ref,
                        page_qualifier='',
                        has_etal='et al' in ref["authors"],
                        normalized_authors=normalized_authors)
        self.assertEqual(get_score_for_input_fields(solution, hypothesis).get_score(), 4.0)

    def test_iter_journal_specific_hypotheses(self):
        """
        test iter_journal_specific_hypotheses
        """
        # "bibcode":"2019BAAS...51c.440B"
        ref = {'title': "Studying the Reionization Epoch with QSO Absorption Lines",
               'authors': "Becker, G., D'Aloisio, A., Davies, F., Hennawi, J., Simcoe, R.",
               'volume': "51",
               'year': "2019",
               'page': "440",
               'journal': "Bulletin of the American Astronomical Society",
               'refstr': "Becker, G., D'Aloisio, A., Davies, F., Hennawi, J., Simcoe, R. (2019). Studying the Reionization Epoch with QSO Absorption Lines. Bulletin of the American Astronomical Society, Vol. 51, p.440."}
        hypothesis = iter_journal_specific_hypotheses('BAAS', ref['authors'], ref['year'], ref['journal'],
                                                              ref['volume'], ref['page'], ref['refstr'])
        tried_hypothesis = ['extra-BAAS->DDA', 'extra-BAAS->AAS', 'extra-BAAS->DPS']
        for i, h in enumerate(hypothesis):
            self.assertEqual(h.name, tried_hypothesis[i])

        # "bibcode":"2009lpsc.book.....A"
        ref = {'title': "Lectures on the Physics of Strongly Correlated Systems XIII",
               'authors': "Avella, A., Mancini, F.",
               'year': "2009",
               'book': "Lectures on the Physics of Strongly Correlated Systems XIII by Adolfo Avella",
               'refstr': "Avella, A., Mancini, F. (2009). Lectures on the Physics of Strongly Correlated Systems XIII by Adolfo Avella, Ferdinando Mancini, Springer, ISBN: 978-0-7354-0699-5"}
        hypothesis = iter_journal_specific_hypotheses('LPSC', ref['authors'], ref['year'], ref['book'],
                                                              None, None, ref['refstr'])
        tried_hypothesis = ['LPSC-ignore-volume']
        for i, h in enumerate(hypothesis):
            self.assertEqual(h.name, tried_hypothesis[i])

        # "bibcode":"2019ApJ...875L..24L"
        ref = {'title': "Simulating the Dark Matter Decay Signal from the Perseus Galaxy Cluster",
               'authors': "Lovell, M., Iakubovskyi, D., Barnes, D., Bose, S., Frenk, C., Theuns, T., Hellwing, W.",
               'year': "2019",
               'volume': "875",
               'page': "L24",
               'journal': "The Astrophysical Journal",
               'refstr': "Lovell, M., Iakubovskyi, D., Barnes, D., Bose, S., Frenk, C., Theuns, T., Hellwing, W., The Astrophysical Journal Letters, Volume 875, Issue 2, article id. L24, 8 pp. (2019)."}
        hypothesis = iter_journal_specific_hypotheses('ApJ', ref['authors'], ref['year'], ref['journal'],
                                                              None, None, ref['refstr'])
        tried_hypothesis = ['extra-ApJ->ApJL']
        for i, h in enumerate(hypothesis):
            self.assertEqual(h.name, tried_hypothesis[i])

        # "bibcode":"2019SPIE10866E....M"
        ref = {'title': "Optogenetics and Optical Manipulation 2019",
               'authors': "Mohanty, S., Jansen, E.",
               'year': "2019",
               'volume': "10866",
               'journal': "Society of Photo-Optical Instrumentation Engineers (SPIE) Conference Series",
               'refstr': "Mohanty, S., Jansen, E., Optogenetics and Optical Manipulation 2019.  Edited by Mohanty, Samarendra K.; Jansen, E. Duco. Proceedings of the SPIE, Volume 10866 (2019)."}
        hypothesis = iter_journal_specific_hypotheses(None, ref['authors'], ref['year'], ref['journal'],
                                                              None, None, ref['refstr'])
        self.assertEqual(next(hypothesis).name, 'fielded-confser-SPIE')

        # "bibcode":"2020JHEP...09..002P"
        ref = {'authors': "Penington, G.",
               'year': "2020",
               'journal': "JHEP",
               'volume': "9",
               'refstr': "Penington, G, 2020, JHEP, 2020, 9"}
        hypothesis = iter_journal_specific_hypotheses(bibstem=None, year=ref['year'], author=ref['authors'], journal=ref['journal'],
                                                      volume=ref['volume'], page=None, full_reference=ref['refstr'])
        self.assertEqual(next(hypothesis).name, 'volume-year-identical')

    def test_get_score_for_baas_match(self):
        """
        test get_score_for_baas_match
        """
        # "bibcode":"2019BAAS...51c.440B"
        solution = {u"identifier":[u"2019astro2020T.440B", u"2019BAAS...51c.440B",
                      u"https://baas.aas.org/wp-content/uploads/2019/05/440_becker.pdf",
                      u"https://baas.aas.org/wp-content/uploads/2019/05/440_becker.pdf",
                      u"2019astro2020T.440B"],
                    u"year":u"2019",
                    u"page":u"440",
                    u"bibcode":"2019BAAS...51c.440B",
                    u"author":[u"Becker, George", u"D'Aloisio, Anson", u"Davies, Frederick B.", u"Hennawi, Joseph F.", u"Simcoe, Robert A."],
                    u"pub":"Bulletin of the American Astronomical Society",
                    u"volume":"51",
                    u"first_author_norm":"Becker, G",
                    u"doctype":"abstract",
                    u"pub_raw":"Astro2020: Decadal Survey on Astronomy and Astrophysics, science white papers, no. 440; Bulletin of the American Astronomical Society, Vol. 51, Issue 3, id. 440 (2019)",
                    u"eid":u"440",
                    u"title":u"Studying the Reionization Epoch with QSO Absorption Lines",
                    u"author_norm":[u"Becker, G", u"D'Aloisio, A", u"Davies, F", u"Hennawi, J", u"Simcoe, R"]}
        input_fields = {'title': "Studying the Reionization Epoch with QSO Absorption Lines",
                        'author': "Becker, G., D'Aloisio, A., Davies, F., Hennawi, J., Simcoe, R.",
                        'volume': "51",
                        'year': "2019",
                        'page': "440",
                        'pub': "Bulletin of the American Astronomical Society",
                        'refstr': "Becker, G., D'Aloisio, A., Davies, F., Hennawi, J., Simcoe, R. (2019). Studying the Reionization Epoch with QSO Absorption Lines. Bulletin of the American Astronomical Society, Vol. 51, p.440."}
        # exact match
        hypothesis = Hypothesis("testing", None,
                       get_score_for_input_fields,
                       input_fields=input_fields,
                       expected_bibstem=get_best_bibstem_for(input_fields["pub"]))
        self.assertEqual(get_score_for_baas_match(solution, hypothesis).get_score(), 1.0)
        # no matching expected_bibcode
        hypothesis = Hypothesis("testing", None,
                       get_score_for_input_fields,
                       input_fields=input_fields,
                       expected_bibstem="no match")
        self.assertEqual(get_score_for_baas_match(solution, hypothesis).get_score(), -1)

    def test_identify_incomplete(self):
        """
        test when parsed reference is incomplete
        """
        ref = {'year': '2020',
               'refstr': '[4] Bennett, J. S., & Sijacki, D. 2020, arXiv e-prints,',
               'authors': 'Bennett, J. S., and Sijacki, D.'}
        with self.assertRaises(Exception) as context:
            solve_reference(Hypotheses(ref))
        self.assertTrue('Not enough information to resolve the record.' in str(context.exception))

    def test_build_bibcode(self):
        """
        test building bibcode to query solr with it
        """
        ref = {'journal': u'a&a',
               'authors': u'Verela et al.',
               'refstr': u'Verela et al., 2016, a&a, 589, 37',
               'volume': u'589',
               'year': u'2016',
               'page': u'37'}
        self.assertEqual(Hypotheses(ref).construct_bibcode(),
                         ['2016A&A...589...37V', '2016?????.589...37?', '2016A&A...589?..37V', '2016?????.589?..37?'])
        ref = {'journal': u'A&A',
               'authors': u'Shakura N. I., Sunyaev R. A.',
               'refstr': u'Shakura N. I., Sunyaev R. A., 1973, A&A, 24, 337',
               'volume': u'24',
               'year': u'1973',
               'page': u'337'}
        self.assertEqual(Hypotheses(ref).construct_bibcode(),
                         ['1973A&A....24..337S', '1973?????..24..337?', '1973A&A....24?.337S', '1973?????..24?.337?'])
        ref = {'journal': u'A&A',
               'authors': u'N. Aghanim et al., Planck Collaboration',
               'refstr': u'N. Aghanim et al., Planck Collaboration, "A&A" 641 (2020) A6.',
               'volume': u'641',
               'year': u'2020',
               'page': u'A6'}
        self.assertEqual(Hypotheses(ref).construct_bibcode(),
                         ['2020A&A...641A...6A', '2020?????.641A...6?'])

class TestResolverSolrQueryCase(TestCase):
    """
    set max number of solr records processing from 100 to 2 to verify no solution is returned
    """
    def create_app(self):
        self.current_app = app.create_app(**{
            'REFERENCE_SERVICE_LIVE': False,
            'REFERENCE_SERVICE_MAX_RECORDS_SOLR': 2
           })
        return self.current_app

    def test_Querier(self):
        solrquery = Querier()
        self.assertEqual(solrquery.query('author:("Accomazzi, A") AND year:"2019" AND bibstem:(AAS)'), None)

if __name__ == "__main__":
    unittest.main()


import torch
from torch import nn, optim
from torchvision import transforms, models, datasets
from torch.utils.data import DataLoader
import numpy as np
from CBAMResnet18 import CBAMResnet18
from visdom import Visdom
'''模型训练'''

batch_size = 256
epochs = 100
learning_rate = 1e-1
seed = 123456
torch.manual_seed(seed)
device = torch.device("cuda:0")

'''猫狗数据集'''
# data_path = "./train"
# transform = transforms.Compose([
#     transforms.Resize((224, 224)),
#     transforms.ToTensor(),
#     transforms.Normalize(mean=[0.485, 0.456, 0.406],
#                         std=[0.229, 0.224, 0.225])
# ])
#
# dataset = MyDataset(data_path, transform)
# train_dataset, test_dataset = torch.utils.data.random_split(dataset, [int(0.8*len(dataset)), len(dataset)-int(0.8*len(dataset))])
# train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
# test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=True)

'''cifar100数据集'''
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                        std=[0.229, 0.224, 0.225])
])
train_loader = DataLoader(datasets.CIFAR100("../data", train=True, transform=transform), batch_size=batch_size, shuffle=True)
test_loader = DataLoader(datasets.CIFAR100("../data", train=False, transform=transform), batch_size=batch_size, shuffle=True)

'''数据可视化'''
# imgs, _ = next(iter(train_loader))
# viz = Visdom()
# viz.images(imgs, win="train")
# exit(0)

''' two classification'''
net = CBAMResnet18(100)
# net = SEResnet18(2)
optimizer = optim.SGD(net.parameters(), lr=learning_rate)
criterion = nn.CrossEntropyLoss()
scheduler = optim.lr_scheduler.StepLR(optimizer, 10, 0.5)
net.to(device)
criterion.to(device)
total_loss = []
viz = Visdom()
viz.line([[0., 0.]], [0.], win="train", opts=dict(title="train&&val loss",
                                                  legend=['train', 'val']))
for epoch in range(epochs):
    net.train()
    total_loss.clear()
    for batch, (input, label) in enumerate(train_loader):
        input, label = input.to(device), label.to(device)
        logits = net(input)
        loss = criterion(logits, label)
        total_loss.append(loss.item())
        loss.backward()
        optimizer.step()

        if batch%50==0:
            print("epoch:{} batch:{} loss:{} lr:{}".format(epoch, batch, loss.item(), optimizer.state_dict()['param_groups'][0]['lr']))
    scheduler.step()

    net.eval()
    correct = 0
    test_loss = 0
    for input, label in test_loader:
        input, label = input.to(device), label.to(device)
        logits = net(input)

        '''crossentropy'''
        test_loss += criterion(logits, label).item() * input.shape[0]
        pred = logits.argmax(dim=1)

        correct += pred.eq(label).float().sum().item()
    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))
    viz.line([[float(np.mean(total_loss)), test_loss]], [epoch], win="train", update="append")
    if (epoch+1)%5==0:
        torch.save(net.state_dict(), "resnet18_{}.pkl".format(epoch))


from __future__ import annotations

from typing import TYPE_CHECKING

from launart import Launart, Service, any_completed

from avilla.onebot.v11.net.ws_client import OneBot11WsClientNetworking
from avilla.onebot.v11.net.ws_server import OneBot11WsServerNetworking

if TYPE_CHECKING:
    from .protocol import OneBot11Protocol

class OneBot11Service(Service):
    id = "onebot11.service"
    required: set[str] = set()
    stages: set[str] = {"preparing", "blocking", "cleanup"}

    connections: list[OneBot11WsClientNetworking | OneBot11WsServerNetworking]
    protocol: OneBot11Protocol

    def __init__(self, protocol: OneBot11Protocol):
        self.connections = []
        self.protocol = protocol
        super().__init__()

    async def launch(self, manager: Launart):
        for conn in self.connections:
            manager.add_component(conn)

        async with self.stage("preparing"):
            ...

        async with self.stage("blocking"):
            await any_completed(
                manager.status.wait_for_sigexit(),
                *(conn.status.wait_for("blocking-completed") for conn in self.connections),
            )

        async with self.stage("cleanup"):
            pass


#import wmm2020
import csv
import math
import numpy as np
from ahrs.filters import EKF
import csv
import os

from constants.definitions import CSV_PATH

with open(CSV_PATH + '/imu_360_sample1.csv') as csv_file:
    reader = csv.reader(csv_file)
    row_count = sum(1 for row in reader)

with open(CSV_PATH + '/imu_360_sample1.csv') as csv_file:
    reader = csv.reader(csv_file)
    acc_data = np.zeros((row_count, 3))
    mag_data = np.zeros((row_count, 3))
    gyr_data = np.zeros((row_count, 3))
    row_num = 0

    for row in reader:
        acc_x = float(row[0][14:])
        acc_y = float(row[1][6:])
        acc_z = float(row[2][6:-1])

        mag_x = float(row[3][13:])
        mag_y = float(row[4][6:])
        mag_z = float(row[5][6:-1])

        gyr_x = float(row[6][14:])
        gyr_y = float(row[7][6:])
        gyr_z = float(row[8][5:-2])
        heading = np.degrees(math.atan2(mag_y, mag_x))
        # print(heading)
        acc_data[row_num] = np.array([acc_x, acc_y, acc_z])
        mag_data[row_num] = np.array([mag_x, mag_y, mag_z])
        gyr_data[row_num] = np.array([gyr_x, gyr_y, gyr_z])

        row_num += 1

# print(acc_data)
# print(mag_data)
# print(gyr_data)

ekf = EKF()
ekf = EKF(gyr=gyr_data, acc=acc_data, mag=mag_data)
# print(ekf.R)
# print(np.shape(ekf.R))
height = np.shape(ekf.R)[0]
for i in range(height):
    top = 2.0 * (ekf.R[i, 2] * ekf.R[i, 3] + ekf.R[i, 0] * ekf.R[i, 1])
    bottom = ekf.R[i, 0] * ekf.R[i, 0] - ekf.R[i, 1] * ekf.R[i, 1] - ekf.R[i, 2] * ekf.R[i, 2] + ekf.R[i, 3] * ekf.R[
        i, 3]

    heading = np.degrees(math.atan2(top, bottom))

    # ekf.R[i,1] = 0;
    # ekf.R[i,3] = 0;
    # m = math.sqrt(ekf.R[i,0]*ekf.R[i,0] + ekf.R[i,2]*ekf.R[i,2]);
    # ekf.R[i,0] /= m
    # ekf.R[i,2] /= m;
    # heading = np.degrees(2*math.acos(ekf.R[i,0]));
    # print(heading)


import numpy as np
import theano
import theano.tensor as T

x = T.matrix('x_sample', dtype='float32')
m = T.max(x, axis=1)
out = m + T.log(T.sum(T.exp(x-m.dimshuffle(0,'x')), axis=1))

f = theano.function([x], [out])

def compute_pdf():
    x = T.matrix('x_sample', dtype='float32')
    mu = T.matrix('mu', dtype='float32')
    sigma = T.matrix('sigma', dtype='float32')
    log_p_reverse = -0.5 * T.sum((T.log(2 * np.pi) + T.log(sigma) + (x - mu) ** 2 / (sigma)),[1])
    log_p_reverse_ = -0.5 * T.sum((T.log(2 * np.pi) + 2 * T.log(sigma) + (x - mu) ** 2 / (2 * sigma**2)),[1])
    #log_p_reverse_ = -0.5 * T.sum((T.abs_(x - mu)),[1])
    f = theano.function([x, mu, sigma], [log_p_reverse, log_p_reverse_])
    return f

f = compute_pdf()
#x_sampled = np.random.normal(0.0, 10.0, size=(100, 784)).clip(0.0, 1.0)
#x_sampled = x_sampled.reshape(100, 784)#n_colors * spatial_width  * spatial_width)

#x_sampled = np.load('batch_3000_corrupted_epoch_30_time_step_29.npz')
x_sampled = x_sampled['X']
x_data = np.asarray(x_sampled).astype('float32')

means_ = np.load('mnist_example.npz')
means_ = means_['arr_0']
means = means_.mean(axis = 0)
means = np.asarray(means).astype('float32')
means = np.array([means,]*100)

vars_ = means_.var(axis = 0)
vars2_ = np.ones([100, 784])
vars_ = np.asarray(vars_).astype('float32')
vars2_ = np.asarray(vars2_).astype('float32')

#vars_ = np.ones([100, 784])
#vars_ = vars_ * 2.0

vars_ = np.array([vars_,]*100)
x_data = x_data.reshape((100, 784))
vars_ = vars_.reshape((100, 784))
vars_ = vars_ + vars2_
vars_ = np.asarray(vars_).astype('float32')
means = means.reshape((100, 784))
log_, log__ = f(x_data, means_, vars_)

'''
experiment_id = '/data/lisatmp3/anirudhg/mnist_walk_back/walkback_-170216T205222'
for batch_index in range(200, 7600, 200):
    qpath = np.load(experiment_id + '/q_path_' + str(batch_index) + '.npz')
    ppath = np.load(experiment_id + '/q_path_' + str(batch_index) +  '_0.npz')

    qsum = np.sum(qpath['X'], axis = 0)
    psum = np.sum(ppath['X'], axis = 0)

    diff = np.sum(psum - qsum, axis = 0)
    diff_ = np.asarray(diff).astype('float32')
    diff_ = diff_.reshape((1,100))
    out = f(diff_)
    print batch_index, diff_.mean()
'''
import ipdb
ipdb.set_trace()


from flask import current_app

from .inference import load_artifact, validate_artifact
from .validate import load_tabular_schema, load_stats

from .. import AppConfig, default_logger

log = default_logger(__name__)

def on_startup(settings: AppConfig) -> bool:
    """
    Startup routine: try to collect application resources:

    + model artifact
    + input data format for requests
    + statistics

    :param settings, `AppConfig`

    :rtype `bool`
    """
    with current_app.app_context():
        log.info(msg="Running startup routine")
        log.debug(msg="Collecting model artifact")

        artifact = load_artifact(settings.artifact_path)
        if not validate_artifact(artifact):
            log.critical(msg="Failed to load artifact, aborting startup")
            return False

        table_schema = load_tabular_schema(settings.table_schema_path)
        if not table_schema:
            log.critical(msg="Failed to load table schema, aborting startup")
            return False

        stats = load_stats(settings.feature_stats_path)
        if not stats:
            msg = "Failed to load statistics for features, aborting statrup"
            log.critical(msg=msg)
            return False

        current_app.config["ARTIFACT"] = artifact
        current_app.config["TABLE_SCHEMA"] = table_schema
        current_app.config["STATS"] = stats
    return True


from PIL import Image,ImageDraw,ImageFont
import imagehash
import image_slicer

tiles =  image_slicer.slice('levels/level0.png', 49,save=False)

# we have 5 component so needed to check all of it(;)

hash1 = imagehash.average_hash(Image.open("comp/solid2_2.png"))
hash2 = imagehash.average_hash(Image.open("comp/empty2_2.png"))
hash3 = imagehash.average_hash(Image.open("comp/player2_2.png"))
hash4 = imagehash.average_hash(Image.open("comp/crate2_2.png"))
hash5 = imagehash.average_hash(Image.open("comp/target2_2.png"))

cutoff = 10  # maximum bits that could be different between the hashes.
# string
for tile in tiles:
    hash0 = imagehash.average_hash(tile.image)
    #soild aka walls
    # print(tile.number)
    if hash0 - hash1 < cutoff:
        print('#', end="")
    elif hash0 - hash2 < cutoff:
        print(' ', end="")
    elif hash0 - hash3 < cutoff:
        print('P', end="")
    elif hash0 - hash4 < cutoff:
        print('B', end="")
    elif hash0 - hash5 < cutoff:
        print('*', end="")

    if tile.number%7 == 0:
        print()

# https://stackoverflow.com/questions/52736154/how-to-check-similarity-of-two-images-that-have-different-pixelization

# https://stackoverflow.com/questions/5953373/how-to-split-image-into-multiple-pieces-in-python

# https://image-slicer.readthedocs.io/en/latest/examples.html

# https://stackoverflow.com/questions/58468944/image-object-has-no-attribute-read


"""Class-based event handlers

A light-weight event-handler framework based on event classes.

Handlers are registered for event classes:

    >>> import zope.event.classhandler

    >>> class MyEvent(object):
    ...     pass

    >>> def handler1(event):
    ...     print("handler1 %r" % event.__class__.__name__)

    >>> zope.event.classhandler.handler(MyEvent, handler1)

Descriptor syntax:

    >>> @zope.event.classhandler.handler(MyEvent)
    ... def handler2(event):
    ...     print("handler2 %r" % event.__class__.__name__)

    >>> class MySubEvent(MyEvent):
    ...     pass

    >>> @zope.event.classhandler.handler(MySubEvent)
    ... def handler3(event):
    ...     print("handler3 %r" % event.__class__.__name__)

Subscribers are called in class method-resolution order, so only
new-style event classes are supported, and then by order of registry.

    >>> import zope.event
    >>> zope.event.notify(MySubEvent())
    handler3 'MySubEvent'
    handler1 'MySubEvent'
    handler2 'MySubEvent'

"""
import zope.event

__all__ = [
    'handler',
]

registry = {}

def handler(event_class, handler_=None, _decorator=False):
    """ Define an event handler for a (new-style) class.

    This can be called with a class and a handler, or with just a
    class and the result used as a handler decorator.
    """
    if handler_ is None:
        return lambda func: handler(event_class, func, True)

    if not registry:
        zope.event.subscribers.append(dispatch)

    if event_class not in registry:
        registry[event_class] = [handler_]
    else:
        registry[event_class].append(handler_)

    if _decorator:
        return handler

def dispatch(event):
    for event_class in event.__class__.__mro__:
        for handler in registry.get(event_class, ()):
            handler(event)


from fastapi import APIRouter, Depends
from app.services.admin import AdminServices
from fastapi.security import OAuth2PasswordRequestForm
from app.models.schemas import (
                                user as _admin_schemas,
                                info as _info_schemas
                                )
from app.services.athu import get_current_user, get_current_admin

router = APIRouter(
    prefix="/admin",
    tags=["admin"],
    responses={404: {"description": "Not found"}}
)

@router.post("/login-form")
async def login_form(form_data: OAuth2PasswordRequestForm = Depends()):
    respon = AdminServices.login_form_admin(form_data)
    return respon

@router.post("/login")
async def get_admin(admin_in: _admin_schemas.UserLogin):
    respon = AdminServices.get_admin(admin_in)
    return respon

@router.post("/create-account")
async def create_admin(admin_create: _admin_schemas.UserCreate, admin_in: dict = Depends(get_current_admin)):
    respon = AdminServices.create_admin(admin_in, admin_create)
    return respon

@router.put("/update-account-info")
async def create_admin(admin_info: _info_schemas.InfoUpdate, admin_in: dict = Depends(get_current_admin)):
    respon = AdminServices.update_admin_info(admin_in, admin_info)
    return respon

@router.get("/get-account-info")
async def create_admin(admin_in: dict = Depends(get_current_admin)):
    respon = AdminServices.get_info_admin_by_id(admin_in)
    return respon

@router.get("/")
async def get_admin(admin_in: dict = Depends(get_current_admin)):

    return admin_in

@router.get("/get-all-admin")
async def get_all_admin(admin_in: dict = Depends(get_current_admin)):
    respon = AdminServices.get_all_admin()
    return respon


#coding: utf-8
from __future__ import print_function

import copy
import warnings

import graphviz # pip install graphviz
# https://stackoverflow.com/questions/35064304/runtimeerror-make-sure-the-graphviz-executables-are-on-your-systems-path-aft
import matplotlib.pyplot as plt
import numpy as np

def plot_stats(statistics, ylog=False, view=False, filename='avg_fitness.svg'):
    """ Cria o gráfico da média da população e melhor fitness. """
    if plt is None:
        warnings.warn("Essa exibição não está disponível devido a uma dependência opicional ausente (matplotlib)")
        return

    generation = range(len(statistics.most_fit_genomes))
    best_fitness = [c.fitness for c in statistics.most_fit_genomes]
    avg_fitness = np.array(statistics.get_fitness_mean())
    stdev_fitness = np.array(statistics.get_fitness_stdev())

    plt.plot(generation, avg_fitness, 'b-', label="average")
    plt.plot(generation, avg_fitness - stdev_fitness, 'g-.', label="-1 sd")
    plt.plot(generation, avg_fitness + stdev_fitness, 'g-.', label="+1 sd")
    plt.plot(generation, best_fitness, 'r-', label="best")

    plt.title("Média da população e melhor fitness")
    plt.xlabel("Gerações")
    plt.ylabel("Fitness")
    plt.grid()
    plt.legend(loc="best")
    if ylog:
        plt.gca().set_yscale('symlog')

    plt.savefig(filename)
    if view:
        plt.show()

    plt.close()

def plot_spikes(spikes, view=False, filename=None, title=None):
    """ Cria o gráfico dos treinos para um single spiking neuron. """
    t_values = [t for t, I, v, u, f in spikes]
    v_values = [v for t, I, v, u, f in spikes]
    u_values = [u for t, I, v, u, f in spikes]
    I_values = [I for t, I, v, u, f in spikes]
    f_values = [f for t, I, v, u, f in spikes]

    fig = plt.figure()
    plt.subplot(4, 1, 1)
    plt.ylabel("Potencial (mv)")
    plt.xlabel("Tempo (in ms)")
    plt.grid()
    plt.plot(t_values, v_values, "g-")

    if title is None:
        plt.title("Izhikevich's spiking neuron model")
    else:
        plt.title("Izhikevich's spiking neuron model ({0!s})".format(title))

    plt.subplot(4, 1, 2)
    plt.ylabel("Fired")
    plt.xlabel("Time (in ms)")
    plt.grid()
    plt.plot(t_values, f_values, "r-")

    plt.subplot(4, 1, 3)
    plt.ylabel("Recovery (u)")
    plt.xlabel("Time (in ms)")
    plt.grid()
    plt.plot(t_values, u_values, "r-")

    plt.subplot(4, 1, 4)
    plt.ylabel("Current (I)")
    plt.xlabel("Time (in ms)")
    plt.grid()
    plt.plot(t_values, I_values, "r-o")

    if filename is not None:
        plt.savefig(filename)

    if view:
        plt.show()
        plt.close()
        fig = None

    return fig

def plot_species(statistics, view=False, filename='speciation.svg'):
    """ Visualiza speciation através da evolução. """
    if plt is None:
        warnings.warn("Essa exibição não está disponível devido a uma dependência opicional ausente (matplotlib)")
        return

    species_sizes = statistics.get_species_sizes()
    num_generations = len(species_sizes)
    curves = np.array(species_sizes).T

    fig, ax = plt.subplots()
    ax.stackplot(range(num_generations), *curves)

    plt.title("Speciation")
    plt.ylabel("Tamanho por Espécies")
    plt.xlabel("Gerações")

    plt.savefig(filename)

    if view:
        plt.show()

    plt.close()

def draw_net(config, genome, view=False, filename=None, node_names=None, show_disabled=True, prune_unused=False,
             node_colors=None, fmt='svg'):
    """ Receives a genome and draws a neural network with arbitrary topology. """
    # Attributes for network nodes.
    if graphviz is None:
        warnings.warn("Essa exibição não está disponível devido a uma dependência opicional ausente (graphviz)")
        return

    if node_names is None:
        node_names = {}

    assert type(node_names) is dict

    if node_colors is None:
        node_colors = {}

    assert type(node_colors) is dict

    node_attrs = {
        'shape': 'circle',
        'fontsize': '9',
        'height': '0.2',
        'width': '0.2'}

    dot = graphviz.Digraph(format=fmt, node_attr=node_attrs)

    inputs = set()
    for k in config.genome_config.input_keys:
        inputs.add(k)
        name = node_names.get(k, str(k))
        input_attrs = {'style': 'filled', 'shape': 'box', 'fillcolor': node_colors.get(k, 'lightgray')}
        dot.node(name, _attributes=input_attrs)

    outputs = set()
    for k in config.genome_config.output_keys:
        outputs.add(k)
        name = node_names.get(k, str(k))
        node_attrs = {'style': 'filled', 'fillcolor': node_colors.get(k, 'lightblue')}

        dot.node(name, _attributes=node_attrs)

    if prune_unused:
        connections = set()
        for cg in genome.connections.values():
            if cg.enabled or show_disabled:
                connections.add((cg.in_node_id, cg.out_node_id))

        used_nodes = copy.copy(outputs)
        pending = copy.copy(outputs)
        while pending:
            new_pending = set()
            for a, b in connections:
                if b in pending and a not in used_nodes:
                    new_pending.add(a)
                    used_nodes.add(a)
            pending = new_pending
    else:
        used_nodes = set(genome.nodes.keys())

    for n in used_nodes:
        if n in inputs or n in outputs:
            continue

        attrs = {'style': 'filled',
                 'fillcolor': node_colors.get(n, 'white')}
        dot.node(str(n), _attributes=attrs)

    for cg in genome.connections.values():
        if cg.enabled or show_disabled:
            #if cg.input not in used_nodes or cg.output not in used_nodes:
            #    continue
            input, output = cg.key
            a = node_names.get(input, str(input))
            b = node_names.get(output, str(output))
            style = 'solid' if cg.enabled else 'dotted'
            color = 'green' if cg.weight > 0 else 'red'
            width = str(0.1 + abs(cg.weight / 5.0))
            dot.edge(a, b, _attributes={'style': style, 'color': color, 'penwidth': width})

    dot.render(filename, view=view)

    return dot


from datetime import datetime
import pandas as pd

from vk_bot.image_handler import ImageHandler

def set_news_data(vk_bot, crawler, start_date, university_name, keywords=None):
    if keywords is None:
        keywords = []
    image_handler = ImageHandler(vk_bot)
    current_crawler = crawler(start_date, keywords)
    news = current_crawler.get_news()
    aggregated_news = pd.DataFrame(columns=["university", "title", "link", "date", "photo_link", "theme"])
    aggregated_news = aggregated_news.append(news)
    for i in range(0, aggregated_news.shape[0]):
        photo_id = image_handler.load_image_for_carousel(aggregated_news.get("photo_link")[i])
        date = datetime.strptime(aggregated_news.get("date")[i], "%d %b %Y").date()
        title = aggregated_news.get("title")[i].strip()
        link = aggregated_news.get("link")[i]
        theme = aggregated_news.get("theme")[i]
        vk_bot.db.add_news(date=date, university=university_name, title=title, link=link, photo_id=photo_id,
                           theme=theme)


# -*- coding: utf-8 -*-

# @Author : 石张毅
# @Site :东莞实业投资控股集团 http://www.dgsy.com.cn
# @introduce:

import scrapy
import copy
from Qinghai.tools.utils import Utils_
from Qinghai.tools.DB_mysql import *
from Qinghai.tools.re_time import Times
import datetime
from Qinghai.tools.uredis import Redis_DB
class DgsySpider(scrapy.Spider):
    name = 'dgsy'
    allowed_domains = ['dgsy.com.cn']
    start_urls = ['http://dgsy.com.cn/']

    def __init__(self, *args, **kwargs ):
        super(DgsySpider, self).__init__()
        self.cates = [
            {"cate": "zbgg", "pages": 1},  # 招标公告

        ]
        self.t = Times()
        self.c_time = datetime.datetime.utcnow() - datetime.timedelta(days=5)

    def start_requests(self):
        url = "http://www.dgsy.com.cn//www/main.jsp?f_treeCode=00190001"

        yield scrapy.FormRequest(url=url, callback=self.parse)

    def parse(self, response):
        # print(response.text)

    #     # 列表页链接和发布时间
        list_url = response.xpath('//*[@class="article_list"]//dd/a/@href').getall()
        # print(list_url)
        titles = response.xpath('//*[@class="article_list"]//dd/a/strong[1]/text()').getall()
        # print(titles)
        pub_times = response.xpath('//*[@class="article_list"]//dd/a/strong[1]/preceding::span[1]/text()').getall()
        #循环遍历
        for href, title, pub_time in zip(list_url, titles, pub_times):
            # print(response.urljoin(href))
            item = {}
            item['link'] = response.urljoin(href.strip())
            item['title'] = title.strip()
            if item['title'] is None:
                continue
            PUBLISH = self.t.datetimes(pub_time)
            item['publish_time'] = PUBLISH.strftime('%Y-%m-%d')  # 发布时间
            item['uid'] = 'zf' + Utils_.md5_encrypt(item['title'] + item['link'] + item['publish_time'])
            ctime = self.t.datetimes(item['publish_time'])

            if Redis_DB().Redis_pd(item['uid']) is True:  # 数据去重
                print(item['uid'], '\033[0;35m <=======此数据已采集=======> \033[0m')
                return
            if ctime < self.c_time:
                print('文章发布时间大于规定时间，不予采集', item['link'])
                return
            yield scrapy.Request(item['link'], callback=self.parse_info, meta={'item': copy.deepcopy(item)},dont_filter=True)

    def parse_info(self, response):
        if response.status != 200:
            return
        item = response.meta['item']
        # 标题
        item['uuid'] = ''

        item['intro'] = ''
        item['abs'] = '1'
        from lxml import etree
        html = etree.HTML(response.text)
        div_data = html.xpath('//*[@class="content_con"]')
        item['content'] = etree.tostring(div_data[0], encoding='utf-8').decode()
        # 购买人
        item['purchaser'] = ''
        item['create_time'] = str(datetime.datetime.now().strftime('%Y-%m-%d'))
        # 代理人
        item['proxy'] = ''
        item['update_time'] = ''

        item['deleted'] = ''
        # 省 份
        item['province'] = '广东|东莞'
        # 基础
        item['base'] = ''
        item['type'] = '招采公告、文件'
        # 行业
        item['items'] = ''
        # 类型编号
        item['data_source'] = '00148'
        item['end_time'] = ''
        item['status'] = ''
        # 采购编号
        item['serial'] = ''

        yield item


# coding:utf-8
import torch
import torch.nn as nn
import torch.nn.functional as F

class ConvBnLeakyRelu2d(nn.Module):
    # convolution
    # batch normalization
    # leaky relu
    def __init__(self, in_channels, out_channels, kernel_size=3, padding=1, stride=1, dilation=1, groups=1):
        super(ConvBnLeakyRelu2d, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, padding=padding, stride=stride, dilation=dilation, groups=groups)
        self.bn   = nn.BatchNorm2d(out_channels)
    def forward(self, x):
        return F.leaky_relu(self.bn(self.conv(x)), negative_slope=0.2)

class MiniInception(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(MiniInception, self).__init__()
        self.conv1_left  = ConvBnLeakyRelu2d(in_channels,   out_channels//2)
        self.conv1_right = ConvBnLeakyRelu2d(in_channels,   out_channels//2, padding=2, dilation=2)
        self.conv2_left  = ConvBnLeakyRelu2d(out_channels,  out_channels//2)
        self.conv2_right = ConvBnLeakyRelu2d(out_channels,  out_channels//2, padding=2, dilation=2)
        self.conv3_left  = ConvBnLeakyRelu2d(out_channels,  out_channels//2)
        self.conv3_right = ConvBnLeakyRelu2d(out_channels,  out_channels//2, padding=2, dilation=2)
    def forward(self,x):
        x = torch.cat((self.conv1_left(x), self.conv1_right(x)), dim=1)
        x = torch.cat((self.conv2_left(x), self.conv2_right(x)), dim=1)
        x = torch.cat((self.conv3_left(x), self.conv3_right(x)), dim=1)
        return x

class MFNet(nn.Module):

    def __init__(self, n_class):
        super(MFNet, self).__init__()
        rgb_ch = [16,48,48,96,96]
        inf_ch = [16,16,16,36,36]

        self.conv1_rgb   = ConvBnLeakyRelu2d(3, rgb_ch[0])
        self.conv2_1_rgb = ConvBnLeakyRelu2d(rgb_ch[0], rgb_ch[1])
        self.conv2_2_rgb = ConvBnLeakyRelu2d(rgb_ch[1], rgb_ch[1])
        self.conv3_1_rgb = ConvBnLeakyRelu2d(rgb_ch[1], rgb_ch[2])
        self.conv3_2_rgb = ConvBnLeakyRelu2d(rgb_ch[2], rgb_ch[2])
        self.conv4_rgb   = MiniInception(rgb_ch[2], rgb_ch[3])
        self.conv5_rgb   = MiniInception(rgb_ch[3], rgb_ch[4])

        self.conv1_inf   = ConvBnLeakyRelu2d(1, inf_ch[0])
        self.conv2_1_inf = ConvBnLeakyRelu2d(inf_ch[0], inf_ch[1])
        self.conv2_2_inf = ConvBnLeakyRelu2d(inf_ch[1], inf_ch[1])
        self.conv3_1_inf = ConvBnLeakyRelu2d(inf_ch[1], inf_ch[2])
        self.conv3_2_inf = ConvBnLeakyRelu2d(inf_ch[2], inf_ch[2])
        self.conv4_inf   = MiniInception(inf_ch[2], inf_ch[3])
        self.conv5_inf   = MiniInception(inf_ch[3], inf_ch[4])

        self.decode4     = ConvBnLeakyRelu2d(rgb_ch[3]+inf_ch[3], rgb_ch[2]+inf_ch[2])
        self.decode3     = ConvBnLeakyRelu2d(rgb_ch[2]+inf_ch[2], rgb_ch[1]+inf_ch[1])
        self.decode2     = ConvBnLeakyRelu2d(rgb_ch[1]+inf_ch[1], rgb_ch[0]+inf_ch[0])
        self.decode1     = ConvBnLeakyRelu2d(rgb_ch[0]+inf_ch[0], n_class)

    def forward(self, x):
        # split data into RGB and INF
        x_rgb = x[:,:3]
        x_inf = x[:,3:]

        # encode
        x_rgb    = self.conv1_rgb(x_rgb)
        x_rgb    = F.max_pool2d(x_rgb, kernel_size=2, stride=2) # pool1
        x_rgb    = self.conv2_1_rgb(x_rgb)
        x_rgb_p2 = self.conv2_2_rgb(x_rgb)
        x_rgb    = F.max_pool2d(x_rgb_p2, kernel_size=2, stride=2) # pool2
        x_rgb    = self.conv3_1_rgb(x_rgb)
        x_rgb_p3 = self.conv3_2_rgb(x_rgb)
        x_rgb    = F.max_pool2d(x_rgb_p3, kernel_size=2, stride=2) # pool3
        x_rgb_p4 = self.conv4_rgb(x_rgb)
        x_rgb    = F.max_pool2d(x_rgb_p4, kernel_size=2, stride=2) # pool4
        x_rgb    = self.conv5_rgb(x_rgb)

        x_inf    = self.conv1_inf(x_inf)
        x_inf    = F.max_pool2d(x_inf, kernel_size=2, stride=2) # pool1
        x_inf    = self.conv2_1_inf(x_inf)
        x_inf_p2 = self.conv2_2_inf(x_inf)
        x_inf    = F.max_pool2d(x_inf_p2, kernel_size=2, stride=2) # pool2
        x_inf    = self.conv3_1_inf(x_inf)
        x_inf_p3 = self.conv3_2_inf(x_inf)
        x_inf    = F.max_pool2d(x_inf_p3, kernel_size=2, stride=2) # pool3
        x_inf_p4 = self.conv4_inf(x_inf)
        x_inf    = F.max_pool2d(x_inf_p4, kernel_size=2, stride=2) # pool4
        x_inf    = self.conv5_inf(x_inf)

        x = torch.cat((x_rgb, x_inf), dim=1) # fusion RGB and INF

        # decode
        x = F.upsample(x, scale_factor=2, mode='nearest') # unpool4
        x = self.decode4(x + torch.cat((x_rgb_p4, x_inf_p4), dim=1))
        x = F.upsample(x, scale_factor=2, mode='nearest') # unpool3
        x = self.decode3(x + torch.cat((x_rgb_p3, x_inf_p3), dim=1))
        x = F.upsample(x, scale_factor=2, mode='nearest') # unpool2
        x = self.decode2(x + torch.cat((x_rgb_p2, x_inf_p2), dim=1))
        x = F.upsample(x, scale_factor=2, mode='nearest') # unpool1
        x = self.decode1(x)

        return x

def unit_test():
    import numpy as np
    x = torch.tensor(np.random.rand(2,4,480,640).astype(np.float32))
    model = MFNet(n_class=9)
    y = model(x)
    print('output shape:', y.shape)
    assert y.shape == (2,9,480,640), 'output shape (2,9,480,640) is expected!'
    print('test ok!')

if __name__ == '__main__':
    unit_test()


from django.db import models
from django.utils.translation import gettext_lazy as _

from izhgtuSite.models import TimeStampedModel

class DateEventPost(TimeStampedModel):
    author = models.ForeignKey(
        "authentication.User",
        verbose_name=_("Author"),
        related_name="dateEventPosts",
        on_delete=models.SET_NULL,
        null=True,
    )

    class Meta:
        verbose_name = _("Date Event Post")
        verbose_name_plural = _("Date Event Posts")

class DateEvent(TimeStampedModel):
    date = models.DateTimeField(_("Date"))
    post = models.ForeignKey(
        DateEventPost,
        verbose_name=_("Post"),
        on_delete=models.SET_NULL,
        related_name="dateEvent",
        null=True,
    )
    name = models.CharField(_("Name"), max_length=150)
    description = models.CharField(_("Description"), max_length=255)
    picture = models.ImageField(_("Picture"), upload_to="dateEventsPictures/")

    class Meta:
        verbose_name = _("Date Event")
        verbose_name_plural = _("Date Events")