class TermHandler(tornado.web.RequestHandler):

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        global cached_term
        if cached_term is not None:
            retjson = {'code':200, 'content':cached_term}
            self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
            self.finish()
            return

        client = AsyncHTTPClient()
        request = HTTPRequest(TERM_URL, request_timeout=TIME_OUT)
        response = yield tornado.gen.Task(client.fetch, request)
        body = response.body
        retjson = {'code':200, 'content':''}
        if not body:
            retjson['code'] = 408
            retjson['content'] = 'time out'
        else:
            soup = BeautifulSoup(body)
            option = soup.findAll('option')
            retjson['content'] = [term.text for term in option]
            cached_term = retjson['content']
            self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()
 class SidebarHandler(tornado.web.RequestHandler):

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum', default=None)
        term = self.get_argument('term', default=None)
        retjson = {'code':200, 'content':''}
        if not (cardnum or term):
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            params = urllib.urlencode(
                {'queryStudentId': cardnum,
                 'queryAcademicYear': term}
            )
            client = AsyncHTTPClient()
            request = HTTPRequest(CURR_URL, body=params, method='POST',
                                  request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            body = response.body
            if not body:
                retjson['code'] = 408
                retjson['content'] = 'time out'
            else:
                pat = re.compile(ur'没有找到该学生信息', re.U)
                match = pat.search(body)
                if match:
                    retjson['code'] = 401
                    retjson['content'] = 'card number not exist'
                else:
                    retjson['content'] = self.parser(body)
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()

    def parser(self, html):
        soup = BeautifulSoup(html)
        items = soup.findAll('td', height='34', width='35%')[:-1]
        items = [item for item in items if item.text != u'&nbsp;']
        sidebar = []
        for item in items:
            sidebar.append(
                {'course': item.text,
                 'lecturer': self.next_n_sibling(item, 2).text[6:],
                 'credit': self.next_n_sibling(item, 4).text[6:],
                 'week': self.next_n_sibling(item, 6).text[6:]
                 })
        return sidebar

    def next_n_sibling(self, item, n):
        for i in xrange(n):
            item = item.nextSibling
        return item
 class CurriculumHandler(tornado.web.RequestHandler):

    def get(self):
        self.write('Herald Web Service')
    @property
    def db(self):
        return self.application.db
    def on_finish(self):
        self.db.close()

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum', default=None)
        term = self.get_argument('term', default=default_term)
        retjson = {'code':200, 'content':'','week':'','term':term}
        if not (cardnum and term):
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            try:
                params = urllib.urlencode(
                    {'queryStudentId': cardnum,
                     'queryAcademicYear': term}
                )
                client = AsyncHTTPClient()
                request = HTTPRequest(
                    CURR_URL, 
                    body=params, 
                    method='POST',
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                body = response.body
                if not body:
                    retjson['code'] = 408
                    retjson['content'] = 'time out'
                else:
                    pat = re.compile(ur'没有找到该学生信息', re.U)

                    match = pat.search(body)
                    if match:
                        retjson['code'] = 401
                        retjson['content'] = 'card number not exist'
                    else:
                        retjson['content'] = self.parser(body)
                        retjson['sidebar'] = self.sidebarparser(body)
                        
                        #url = "http://58.192.114.179/classroom/common/gettermlistex"
                        #client = AsyncHTTPClient()
                        #request = HTTPRequest(
                        #    url = url, 
                        #    method = "GET",
                        #    request_timeout=3
                        #)
                        #response = yield tornado.gen.Task(client.fetch, request)
                        #content = json.loads(response.body)
                        #termTemp = term.split('-')
                        #term = "20"+termTemp[0]+"-"+"20"+termTemp[1]+"-"+termTemp[2]
                        retjson['content']['startdate']={
                            'month': start_date.month - 1,
                            'day'  : start_date.day
                        }
                        # for i in content:
                        #     if i['code'] == term:
                        #         retjson['content']['startdate']['month'] = i['startDate']['month']
                        #         retjson['content']['startdate']['day'] = i['startDate']['date']
                        #         break

            except Exception,e:
                retjson['code'] = 500
                print traceback.print_exc()
                retjson['content'] = str(e)
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()

    def parser(self, html):
        soup = BeautifulSoup(html)
        table = soup.findAll('td', rowspan='5')
        table += soup.findAll('td', rowspan='2')
        self.course_split(table[1])
        curriculum = OrderedDict()
        curriculum['Mon'] = self.course_split(table[1]) + \
            self.course_split(table[7]) + \
            self.course_split(table[13])
        curriculum['Tue'] = self.course_split(table[2]) + \
            self.course_split(table[8]) + \
            self.course_split(table[14])
        curriculum['Wed'] = self.course_split(table[3]) + \
            self.course_split(table[9]) + \
            self.course_split(table[15])
        curriculum['Thu'] = self.course_split(table[4]) + \
            self.course_split(table[10]) + \
            self.course_split(table[16])
        curriculum['Fri'] = self.course_split(table[5]) + \
            self.course_split(table[11]) + \
            self.course_split(table[17])
        curriculum['Sat'] = self.course_split(table[19])
        curriculum['Sun'] = self.course_split(table[21])

        return curriculum

    def course_split(self, table):
        br = BeautifulSoup('<br/>')
        course = []
        for item in table.contents[:-1]:
            course.append(item)
            try:
                if course[-1] == course[-2] == br.br:
                    course.insert(-1, u'')
            except IndexError:
                pass  # 忽略第一次迭代时 course 越界
        course = [item for item in course if item != br.br]

        curriculum = []
        for i in xrange(0, len(course), 3):
            curriculum.append(
                [course[i].strip(), course[i + 1], course[i + 2]]
            )
        return curriculum

    def sidebarparser(self, html):
        soup = BeautifulSoup(html)
        items = soup.findAll('td', height='34', width='35%')[:-1]
        items = [item for item in items if item.text != u'&nbsp;']
        sidebar = []
        for item in items:
            sidebar.append(
                {'course': item.text.strip(),
                 'lecturer': self.next_n_sibling(item, 2).text[6:],
                 'credit': self.next_n_sibling(item, 4).text[6:],
                 'week': self.next_n_sibling(item, 6).text[6:]
                 })
        return sidebar

    def next_n_sibling(self, item, n):
        for i in xrange(n):
            item = item.nextSibling
        return item class SIMSIMIHandler(tornado.web.RequestHandler):

    def get(self):
        self.post()
        #self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        msg = self.get_argument('msg', default='你好')
        uid = self.get_argument('uid', default='')
        data = {
            'key': KEY,
            'info': msg,
            'loc': '江苏南京江宁',
            'userid': uid
        }
        try:
            client = AsyncHTTPClient()
            request = HTTPRequest(
                TULING_URL + urllib.urlencode(data),
                method='GET',
                request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            retjson = json.loads(response.body)
            self.write(self.msgmap[retjson['code']](retjson).replace(u'小Q',u'小猴'))
        except Exception,e:
            self.write('error')
        self.finish()

        # msg = self.get_argument('msg', default='hello')
        # try:
        #     client = AsyncHTTPClient()
        #     request = HTTPRequest(
        #         SIMSIMI_URL + msg,
        #         method='GET',
        #         request_timeout=TIME_OUT,
        #         headers={'Cookie': COOKIE, 'User-Agent': AGENT})
        #     response = yield tornado.gen.Task(client.fetch, request)
        #     x = json.loads(response.body.decode('utf8'))
        #     if x[u'msg'] == 'OK':
        #         self.write(x[u'sentence_resp'].encode('utf8'))
        #         self.finish()
        #     else:
        #         self.write('error')
        #         self.finish()
        # except:
        #     self.write('error')
        #     self.finish()
    @property
    def msgmap(self):
        return {
            100000 : self.text,
            200000 : self.link,
            301000 : self.book,
            302000 : self.news,
            304000 : self.app,
            305000 : self.train,
            306000 : self.plane,
            307000 : self.shopping,
            308000 : self.movie,
            309000 : self.hotel,
            310000 : self.lottery,
            311000 : self.price,
            312000 : self.restaurant,
            50000 : self.error,
            40004 : self.useoff,
        }

    def useoff(self, data):
        return u'小猴累了，回家休息了，明天再来找TA吧'

    def text(self, data):
        return data['text']

    def link(self, data):
        return u'不如用电脑查查，么么哒'

    def book(self, data):
        msg = u'[图书]\n'
        for b in data['list']:
            msg += u'<%s> %s\n'%(b['name'], b['author'])
        return msg

    def news(self, data):
        msg = u'[新闻]\n'
        for n in data['list']:
            msg += u'<a href="%s">%s</a>\n'%(n['detailurl'],n['article'])
        return msg

    def app(self, data):
        msg = u'[应用]\n'
        for a in data['list']:
            msg += u'%s\n'%a['name']
        return msg

    def train(self, data):
        return u'不如用电脑查查，么么哒'

    def plane(self, data):
        return u'不如用电脑查查，么么哒'

    def shopping(self, data):
        return u'不如用电脑查查，么么哒'

    def movie(self, data):
        return u'不如用电脑查查，么么哒'

    def hotel(self, data):
        return u'不如用电脑查查，么么哒'

    def lottery(self, data):
        return u'不如用电脑查查，么么哒'

    def price(self, data):
        return u'不如用电脑查查，么么哒'

    def restaurant(self, data):
        return u'不如用电脑查查，么么哒'

    def error(self, data):
        return data['text'] class GPAHandler(tornado.web.RequestHandler):
    @property
    def db(self):
        return self.application.db
    def on_finish(self):
        self.db.close()
    
    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        username = self.get_argument('username', default=None)
        pwd = self.get_argument('password', default=None)
        status = None

        retjson = {'code':200, 'content':''}
        if not (username or pwd):
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            # read from cache
            try:
                status = self.db.query(GpaCache).filter(GpaCache.cardnum == username).one()
                if status.date > int(time())-gpaCacheTime and status.text != '*':
                    self.write(base64.b64decode(status.text))
                    self.finish()
                    return
            except NoResultFound:
                status = GpaCache(cardnum = username,text = '*',date = int(time()))
                self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()

            client = AsyncHTTPClient()
            request = HTTPRequest(VERCODE_URL, request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            if not response.headers:
                retjson['code'] = 408
                retjson['content'] = 'time out'
            else:
                cookie = response.headers['Set-Cookie'].split(';')[0]#+";"+response.headers['Set-Cookie'].split(';')[1].split(',')[1]
                img = Image.open(io.BytesIO(response.body))
                vercode = self.recognize(img)
                params = urllib.urlencode({
                    'userName': username,
                    'password': pwd,
                    'vercode': vercode
                })
                request = HTTPRequest(LOGIN_URL, body=params, method='POST',
                                      headers={'Cookie': cookie},
                                      request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                if not response.headers:
                    retjson['code'] = 408
                    retjson['content'] = 'time out'
                else:
                    if 'vercode' in response.body:
                        retjson['code'] = 401
                        retjson['content'] = 'wrong card number or password'
                    else:
                        request = HTTPRequest(INFO_URL,
                                              request_timeout=TIME_OUT,
                                              headers={'Cookie': cookie})
                        response = yield tornado.gen.Task(client.fetch, request)
                        if not response.headers:
                            retjson['code'] = 408
                            retjson['content'] = 'time out'
                        else:
                            retjson['content'] = self.parser(response.body)
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()
        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except Exception,e:
                self.db.rollback()
            finally:
                self.db.remove()

    def recognize(self, img):
        start = [13, 59, 105, 151]
        result = ''
        for i in start:
            sample = []
            for i in xrange(i, i + 40):
                temp = 0
                for j in xrange(0, 100):
                    temp += (img.getpixel((i, j))[1] < 40)
                sample.append(temp)
            min_score = 1000
            max_match = 0
            for idx, val in enumerate(STANDARD):
                diff = []
                for i in xrange(len(sample)):
                    diff.append(sample[i] - val[i])
                avg = float(sum(diff)) / len(diff)

                for i in xrange(len(sample)):
                    diff[i] = abs(diff[i] - avg)
                score = sum(diff)
                if score < min_score:
                    min_score = score
                    max_match = idx

            result = result + str(max_match)
        return result

    def parser(self, html):
        soup = BeautifulSoup(html)
        trs = soup.findAll('tr')
        items = []
        credit = trs[-1].findAll('td')
        items.append({
            'gpa': credit[0].text,
            'gpa without revamp': credit[1].text,
            'calculate time': credit[-1].text[6:-6]
        })
        for i in xrange(2, len(trs) - 4):
            tds = trs[i].findAll('td')
            items.append({
                'semester': tds[1].text,
                'name': tds[3].text[:-6],
                'credit': tds[4].text[:-6],
                'score': tds[5].text[:-6],
                'type': tds[6].text[:-6],
                'extra': tds[7].text[:-6]
            })
        return items class PEHandler(tornado.web.RequestHandler):
    # 为查跑操的 TCP Client 建立线程池
    executor = ThreadPoolExecutor(10)

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write('Herald Web Service')

    def on_finish(self):
        self.db.close()


    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        state = 'success'
        cardnum = self.get_argument('cardnum', default=None)
        pwd = self.get_argument('pwd', default=cardnum)
        retjson = {'code':200, 'content':''}
        # pwd 缺省为 cardnum

        if not cardnum:
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            result = yield self.get_pe_count(cardnum)

            if result == -1:
                state = 'time_out'
                try:
                    # 超时取出缓存
                    user = self.db.query(PEUser).filter(
                        PEUser.cardnum == int(cardnum)).one()
                    retjson['content'] = user.count
		    retjson['rank'] = self.get_rank(user.count)
                    retjson['remain'] = self.get_remain_day()
                except NoResultFound:
                    retjson['remain'] = self.get_remain_day()
                    retjson['code'] = 408
                    retjson['content'] = 'time out'
            else:
                retjson['content'] = str(result)
		retjson['rank'] = self.get_rank(result)
                retjson['remain'] = self.get_remain_day()
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()

        if state == 'success':
            # 更新缓存
            try:
                user = self.db.query(PEUser).filter(
                    PEUser.cardnum == int(cardnum)).one()
                user.count = int(result)
            except NoResultFound:
                user = PEUser(cardnum=int(cardnum), count=int(result))
                self.db.add(user)
            finally:
                self.db.commit()
        self.db.close()
    def get_rank(self, count):
        global last_refresh
        global all_count
        global all_sum
        try:
            if last_refresh + 300 < int(time()):
                last_refresh = int(time())
                db_instance = self.db.execute("select count, count(*) as all_sum from pe group by count").fetchall()
                all_count = {}
                all_sum = 0
                for item in db_instance:
                    all_count[item.count] = int(item.all_sum)
                    all_sum += int(item.all_sum)
            temp_sum = 0
            for i, j in all_count.items():
                if int(i) >= int(count):
                    temp_sum += all_count[i]
            return '%.2f' % ((float(all_sum)-temp_sum)/all_sum*100)
        except Exception,e:
            return '0'

    # 把查跑操的 TCP 连接放在线程池中运行
    @run_on_executor
    def get_pe_count(self,cardnum):
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.settimeout(3)
        try:
            s.connect((API_SERVER_HOST, API_SERVER_PORT))
            s.send('\x00'+A+'\x09'+cardnum+'\x00')
            recv = s.recv(1024).split(',')
            return int(recv[0])+int(recv[1])
        except socket.timeout:
            return -1
        except:
            return -1

    def get_remain_day(self):
        def weekends_between(start, end):
            days_between = (end - start).days
            weekends, leftover = divmod(days_between, 7)
            if leftover:
                start_day = (end-timedelta(leftover)).isoweekday()
                end_day = start_day + leftover
                if start_day <= 6 and end_day > 6:
                    weekends += .5
                if start_day <= 7 and end_day > 7:
                    weekends += .5
            return weekends
        
        final = end_date + timedelta(days=1)
        now = datetime.now()
        current_day = date(now.year, now.month, now.day)
        """
        如果超过八点，按后天计算
        """
        if now.hour > 8:
            current_day = current_day + timedelta(days=1)
        else:
            pass
        """
        跑操最后一次操的那天-今天-所有之间的双休日
        """
        remain_days = int((final - current_day).days - weekends_between(current_day, final)*2)
        if (remain_days <= 0):
            remain_days = 0
        return remain_days
        
        """
        finay_day_strp = strptime(finay_day,"%Y-%m-%d")
        final = datetime.datetime(finay_day_strp[0],finay_day_strp[1],finay_day_strp[2])
        current_day_strp = strptime(strftime('%Y-%m-%d', localtime(time())),"%Y-%m-%d")
        current = datetime.datetime(current_day_strp[0],current_day_strp[1],current_day_strp[2])
        alldays = (final-current).days
        current_date = daymap[strftime('%a', localtime(time()))]
        front_remain = 7-current_date
        front_day = 6-current_date
        front_day = front_day if front_day>0 else 0
        back_remain = 5
        all_week = (alldays-5-front_remain)/7
        workday_count = (all_week+1)*5+front_day
        if current_date<=6:
            workday_count = workday_count-1
        return workday_count if workday_count > 0  else 0
        """ class ticeInfoHandler(tornado.web.RequestHandler):
    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum',default=None)
        retjson = {'code':200,'content':''}
        state = 'fail'
        if not cardnum:
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            #read from cache
            try:
                status = self.db.query(TiceCache).filter(TiceCache.cardnum == cardnum).one()
                if status.date > int(time()-30000) and status.text != '*':
                    self.write(base64.b64decode(status.text))
                    self.finish()
                    return
            except NoResultFound:
                status = TiceCache(cardnum = cardnum,text='*',date = int(time()))
                self.db.add(status)
            try:
                sefl.db.commit()
            except:
                self.db.rollback()

            try:
                result = self.get_tice_info(cardnum)
                if result == -1:
                    retjson['code'] = 408
                    retjson['content'] = 'time out'
                else:
                    state = 'success'
                    retjson['content'] = result
            except Exception,e:
                retjson['code'] = 500
                retjson['content'] = str(e)
        ret = json.dumps(retjson,ensure_ascii=False,indent=2)
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()

        #refresh cache

        if state == 'success':
            try:
                status.date = int(time())
                status.text = base64.b64encode(ret)
                self.db.add(status)
                self.db.commit()
            except:
                self.db.rollback()
    def get_tice_info(self,cardnum):
        try:
            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)   
            s.settimeout(3)  
            s.connect((API_SERVER_HOST, API_SERVER_PORT))
            s.send('\x01'+A+'\x09'+cardnum+'\x00')
            recv = s.recv(1024).split(',')
            ret = {
                'height':recv[0],
                'weight':recv[1],
                'fei':{
                    'value':recv[2],
                    'score':recv[3],
                    'comment':recv[4].decode('gbk').encode('utf-8')
                },
                '50meter':{
                    'value':recv[5],
                    'score':recv[6],
                    'comment':recv[7].decode('gbk').encode('utf-8')
                },
                'jump':{
                    'value':recv[8],
                    'score':recv[9],
                    'comment':recv[10].decode('gbk').encode('utf-8')
                },
                '1000meter':{
                    'value':recv[14],
                    'score':recv[15],
                    'comment':recv[16].decode('gbk').encode('utf-8')
                },
                'zuoqian':{
                    'value':recv[17],
                    'score':recv[18],
                    'comment':recv[19].decode('gbk').encode('utf-8')
                },
                'up-down':{
                    'value':recv[20],
                    'score':recv[21],
                    'comment':recv[22].decode('gbk').encode('utf-8')
                },
                'score':recv[23].decode('gbk').encode('utf-8')
            }
            return ret
        except:
            return -1 class pedetailHandler(tornado.web.RequestHandler):
    @property
    def db(self):
        return self.application.db
    def on_finish(self):
        self.db.close()
    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        retjson = {'code':200,'content':''}
        cardnum = self.get_argument('cardnum',default=None)
        password = self.get_argument('password',default=None)
        if not (cardnum and password):
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            # read from cache
            try:
                status = self.db.query(PeDetailCache).filter(PeDetailCache.cardnum == cardnum).one()
                if int(strftime('%H', localtime(time())))<8 or (status.date > int(time())-10000 and status.text != '*'):
                    if status.text == '*':
                        retjson['content'] = []
                        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
                        self.finish()
                        return  
                    self.write(base64.b64decode(status.text))
                    self.finish()
                    return
            except NoResultFound:
                status = PeDetailCache(cardnum = cardnum,text = '*',date = int(time()))
                self.db.add(status)
                try:
                    self.db.commit()
                except:
                    self.db.rollback()

            try:
                client = AsyncHTTPClient()
                data = {
                    "Login.Token1" : cardnum,
                    "Login.Token2" : password,
                    'goto' : "http://mynew.seu.edu.cn/loginSuccess.portal",
                    'gotoOnFail' : "http://mynew.seu.edu.cn/loginFailure.portal"
                }
                data1 = {
                    'IDToken0':   '',
                    'IDToken1':cardnum,
                    'IDToken2':password,
                    'IDButton':'Submit',
                    'goto':'http://zccx.seu.edu.cn/',
                    'gx_charset':'gb2312'
                }

                cookie1 = ''
                request = HTTPRequest(
                    loginurl1,
                    method='POST',
                    body = urllib.urlencode(data1),
                    follow_redirects=False,
                    connect_timeout=2,
                    request_timeout=3
                )
                initcookie = ''
                try:
                    response = yield client.fetch(request)
                except HTTPError as e:
                    initcookie = e.response.headers['Set-Cookie']
                init_cookie1 = initcookie.split(';')[4].split(',')[1]#+initcookie.split(';')[0]
                header = {
                    'Host':'zccx.seu.edu.cn',
                    'Accept': 'textml,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36',
                    'Referer':'http://zccx.seu.edu.cn/',
                    'Connection':'Keep-alive',
                    'Accept-Encoding': 'gzip, deflate',
                    'Accept-Language': 'zh-CN,zh;q=0.8',
                    'Cookie':init_cookie1+';'+cookie1+';'+';amblcookie=02'
                }
                request = HTTPRequest(
                    runurl,
                    method='GET',
                    headers = header,
                    connect_timeout=2,
                    request_timeout=3
                )
                
                response = yield client.fetch(request)
                cookie1 = response.headers['Set-Cookie']
                header['Cookie'] = init_cookie1+';'+cookie1+';'+';amblcookie=02'  
                getpeurl = "http://zccx.seu.edu.cn/SportWeb/gym/gymExercise/gymExercise_query_result_2.jsp?xh=%s"%(cardnum)
                request = HTTPRequest(
                    getpeurl,
                    headers = header,
                    connect_timeout=2,
                    request_timeout=8
                    )
                response = yield client.fetch(request)
                spider = RunningParser()
                spider.getRunningTable(response.body)
                retjson['content'] = spider.table
            except Exception,e:
                retjson['code'] = 500
                retjson['content'] = str(e)
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except Exception,e:
                self.db.rollback()
            finally:
                self.db.remove() class SRTPHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db
    def on_finish(self):
        self.db.close()
    def get(self):
        self.write('Herald Web Service')


    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        number = self.get_argument('number', default=None)
        retjson = {'code':200, 'content':''}
        status = None

        if not number:
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            #read from cache
            try:
                status = self.db.query(SRTPCache).filter(SRTPCache.cardnum == number).one()
                if status.date > int(time())-srtpCacheTime and status.text != '*':
                        self.write(base64.b64decode(status.text))
                        self.finish()
                        return
            except NoResultFound:
                status = SRTPCache(cardnum = number,text = '*',date = int(time()))
                self.db.add(status)
                try:
                    self.db.commit()
                except:
                    self.db.rollback()

            params = urllib.urlencode({'Code': number})
            client = AsyncHTTPClient()
            request = HTTPRequest(SRTP_URL, body=params, method='POST',
                                  request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            if not response.headers:
                retjson['code'] = 408
                retjson['content'] = 'time out'
            else:
                pat = re.compile('不存在|请输入', re.U)
                match = pat.search(response.body)
                if match:
                    retjson['code'] = 401
                    retjson['content'] = 'number not exist'
                else:
                    retjson['content'] = self.parser(response.body)
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except Exception,e:
                self.db.rollback()
            finally:
                self.db.remove()

    def parser(self, html):
        soup = BeautifulSoup(html)
        trs = soup.findAll('tr')

        name = trs[6].text.split(u'&nbsp;')[3].split(u'：')[1]
        cardnum = trs[6].text.split(u'&nbsp;')[1].split(u'：')[1]
        total = trs[-2].findAll('td')[-1].text
        score = trs[-1].findAll('td')[-1].text
        trs = trs[8:-2]
        srtp = [{
            'name': name,
            'card number': cardnum,
            'total': total,
            'score': score
        }]
        for td in trs:
            tds = td.findAll('td')
            srtp.append({
                'type': tds[0].text.replace('-', ''),
                'project': tds[1].text.replace('  ', ''),
                'date': tds[2].text.replace('-', ''),
                'department': tds[3].text.replace('-', ''),
                'total credit': tds[4].text.replace('-', ''),
                'proportion': tds[5].text.replace('-', ''),
                'credit': tds[6].text.replace('-', ''),
            })
        return srtp class CARDHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db
    def on_finish(self):
        self.db.close()
        
    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        timedelta = int(self.get_argument('timedelta', default=0))
        # if int(timedelta)>7:
        #     timedelta = 7
        cardnum = self.get_argument('cardnum')
        cardnum_with_delta = cardnum + str(timedelta)
        data = {
            'Login.Token1':cardnum,
            'Login.Token2':self.get_argument('password'),
        }
        retjson = {'code':200, 'content':''}

        # read from cache
        try:
            status = self.db.query(CardCache).filter( CardCache.cardnum ==  cardnum_with_delta ).one()
            if status.date > int(time())-cardCacheTime and status.text != '*':
                self.write(base64.b64decode(status.text))
                self.db.close()
                self.finish()
                return
        except NoResultFound:
            status = CardCache(cardnum=cardnum_with_delta, text='*', date=int(time()))
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()

        try:
            client = AsyncHTTPClient()
            response = authApi(cardnum,self.get_argument('password'))
            if response['code']==200:
                cookie = response['content']
                request = HTTPRequest(
                    LOGIN_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                cookie += ';' + response.headers['Set-Cookie'].split(';')[0]
                request = HTTPRequest(
                    USERID_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)

                soup = BeautifulSoup(response.body)
                td = soup.findAll('td',{"class": "neiwen"})
                userid = td[3].text
                cardState = td[42].text
                cardLetf = td[46].text.encode('utf-8').split('元')[0]
                # do not need to get the detail
                if timedelta == 0:
                    retjson['content'] = {'state':cardState, 'left': cardLetf, 'cardLeft':cardLetf}
                    ret = json.dumps(retjson, ensure_ascii=False, indent=2)
                    self.write(retjson)
                    self.finish()

                    # refresh cache
                    if retjson['code'] == 200:
                        status.date = int(time())
                        status.text = base64.b64encode(ret)
                        self.db.add(status)
                        try:
                            self.db.commit()
                        except:
                            self.db.rollback()
                        finally:
                            self.db.remove()
                    self.db.close()
                    return
                #get today detail
                elif timedelta == 1:
                    data = {
                        'account':userid,
                        'inputObject':"all",
                    }
                    request = HTTPRequest(
                        TODAYDATA_URL,
                        method='POST',
                        body=urllib.urlencode(data),
                        headers={'Cookie':cookie},
                        request_timeout=TIME_OUT
                    )
                    response = yield tornado.gen.Task(client.fetch, request)
                    soup = BeautifulSoup(response.body.decode('gb2312','ignore'))
                    tr = soup.findAll('tr',{"class": re.compile("listbg")})
                    detail=[]
                    for td in tr:
                            td = td.findChildren()
                            tmp = {}
                            tmp['date'] = td[0].text
                            tmp['type'] = td[3].text
                            tmp['system'] = td[4].text
                            tmp['price'] = td[5].text
                            tmp['left'] = td[6].text
                            detail.append(tmp)
                    retjson['content'] = {'state':cardState, 'left': cardLetf, 'cardLeft':cardLetf,'detail':detail, 'detial': detail}
                #get other days detail depend on timedelta
                else:
                    request = HTTPRequest(
                        INIT_URL,
                        method='GET',
                        headers={'Cookie':cookie},
                        request_timeout=TIME_OUT)
                    response = yield tornado.gen.Task(client.fetch, request)
                    soup = BeautifulSoup(response.body)
                    __continue = soup.findAll('form',{'id':'accounthisTrjn1'})[0]['action']

                    now = datetime.datetime.now()
                    delta = datetime.timedelta(timedelta)
                    page = 1
                    data = {
                        'account':userid,
                        'inputObject':'all',
                        'inputStartDate':(now - delta).strftime('%Y%m%d'),
                        'inputEndDate':now.strftime('%Y%m%d'),
                        'pageNum':page
                    }
                    request = HTTPRequest(
                        INDEX_URL+__continue,
                        method='POST',
                        headers={'Cookie':cookie},
                        body=urllib.urlencode(data),
                        request_timeout=TIME_OUT)
                    response = yield tornado.gen.Task(client.fetch, request)
                    soup = BeautifulSoup(response.body.decode('gb2312','ignore'))
                    __continue = soup.findAll('form',{'id':'accounthisTrjn2'})[0]['action']
                    request = HTTPRequest(
                        INDEX_URL+__continue,
                        method='POST',
                        headers={'Cookie':cookie},
                        body=urllib.urlencode(data),
                        request_timeout=TIME_OUT)
                    response = yield tornado.gen.Task(client.fetch, request)
                    soup = BeautifulSoup(response.body.decode('gb2312','ignore'))
                    __continue = 'accounthisTrjn3.action'
                    request = HTTPRequest(
                        INDEX_URL+__continue,
                        method='POST',
                        headers={'Cookie':cookie},
                        body=urllib.urlencode(data),
                        request_timeout=TIME_OUT)
                    response = yield tornado.gen.Task(client.fetch, request)
                    soup = BeautifulSoup(response.body.decode('gb2312','ignore'))
                    detial = []
                    count = 0
                    while 1:
                        tr = soup.findAll('tr',{"class": re.compile("listbg")})
                        if not tr:
                            break
                        for td in tr:
                            td = td.findChildren()
                            tmp = {}
                            tmp['date'] = td[0].text
                            tmp['type'] = td[3].text#.encode('ISO-8859-1').decode('gbk')
                            tmp['system'] = td[4].text#.encode('ISO-8859-1').decode('gbk')
                            tmp['price'] = td[5].text
                            tmp['left'] = td[6].text
                            if(tmp['type']== u'扣款'):
                                tmp['type'] = '水电扣费'
                            detial.append(tmp)
                        page += 1
                        data['pageNum'] = page
                        request = HTTPRequest(
                            DATA_URL,
                            method='POST',
                            headers={'Cookie':cookie},
                            body=urllib.urlencode(data),
                            request_timeout=TIME_OUT)
                        response = yield tornado.gen.Task(client.fetch, request)
                        soup = BeautifulSoup(response.body.decode('gb2312','ignore'))
                    retjson['content'] = {'state':cardState, 'left': cardLetf, 'cardLeft':cardLetf, 'detail':detial, 'detial': detial}
            else:
                retjson['code'] = 401
                retjson['content'] = 'wrong card number or password'
        except Exception,e:
            retjson['code'] = 500
            retjson['content'] = str(e)

        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()
        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(str(ret))
            self.db.add(status)
            try:
                self.db.commit()
            
            except:
                self.db.rollback()
            finally:
                self.db.remove() class NICHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum')
        data = {
            'username':cardnum,
            'password':self.get_argument('password'),
        }
        retjson = {'code':200, 'content':''}

        # read from cache
        try:
            status = self.db.query(NicCache).filter( NicCache.cardnum ==  cardnum ).one()
            if status.date > int(time())-600 and status.text != '*':
                self.write(base64.b64decode(status.text))
                self.db.close()
                self.finish()
                return
        except NoResultFound:
            status = NicCache(cardnum=cardnum, text='*', date=int(time()))
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()

        try:
            client = AsyncHTTPClient()
            client2 = HTTPClient()
            request = HTTPRequest(
                LOGIN_URL,
                method='GET',
                request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            cookie = response.headers['Set-Cookie'].split(';')[0]
            request = HTTPRequest(
                LOGIN_URL,
                method='POST',
                body = urllib.urlencode(data),
                headers={'Cookie':cookie},
                request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            if len(response.body) > 10000:
                ret = {}
                self.chose_type(client2, cookie, 'a')
                request = HTTPRequest(
                    DETIAL_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = client2.fetch(request)
                if len(response.body) > 10000:
                    soup = BeautifulSoup(response.body)
                    td = soup.findAll('td', {'bgcolor': '#FFFFFF', 'align': re.compile('center|right')})
                    if td[1].text[:-14]:
                        ret['a'] = {'state': td[0].text, 'used': td[1].text[:-14]+'B'}
                    else:
                        ret['a'] = {'state': td[0].text, 'used': td[2].text[:-14]+'B'}
                else:
                    ret['a'] = {'state':'未开通'.decode('utf-8'), 'used':'0 B'}

                self.chose_type(client2, cookie, 'b')
                request = HTTPRequest(
                    DETIAL_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = client2.fetch(request)
                if len(response.body) > 10000:
                    soup = BeautifulSoup(response.body)
                    td = soup.findAll('td', {'bgcolor': '#FFFFFF', 'align': re.compile('center|right')})
                    if td[1].text[:-14]:
                        ret['b'] = {'state': td[0].text, 'used': td[1].text[:-14]+'B'}
                    else:
                        ret['b'] = {'state': td[0].text, 'used': td[2].text[:-14]+'B'}
                else:
                    ret['b'] = {'state':'未开通'.decode('utf-8'), 'used':'0 B'}

                self.chose_type(client2, cookie, 'web')
                request = HTTPRequest(
                    WEB_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = client2.fetch(request)
                if len(response.body) > 10000:
                    soup = BeautifulSoup(response.body)
                    td = soup.findAll('td', {'bgcolor': '#FFFFFF', 'align': 'center'})
                    ret['web'] = {'state': td[0].text+','+td[1].text, 'used': td[-1].text}
                else:
                    ret['web'] = {'state':'未开通'.decode('utf-8'), 'used':'0 B'}

                request = HTTPRequest(
                    FEE_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                soup = BeautifulSoup(response.body)
                td = soup.findAll('td', {'bgcolor': '#FFFFFF', 'align': 'center'})
                ret['left'] = td[0].text

                retjson['content'] = ret
            else:
                retjson['code'] = 401
                retjson['content'] = 'wrong card number or password'
        except:
            retjson['code'] = 500
            retjson['content'] = 'error'
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()
            finally:
                self.db.remove()
        self.db.close()

    def chose_type(self, client, cookie, type):
        data = {
            'operation': 'status',
            'item': type,
            'web_sel':1,
        }
        request = HTTPRequest(
            CHOISE_URL,
            method='POST',
            body = urllib.urlencode(data),
            headers={'Cookie':cookie},
            request_timeout=TIME_OUT)
        response = client.fetch(request) class AuthHandler(tornado.web.RequestHandler):

    def get(self):
        self.write('Herald Web Service')

   
    def post(self):
        result = authApi(self.get_argument('cardnum'),self.get_argument('password'))
        if(result['code']==200):
            self.write(result['content'])
            self.finish()
        elif (result['code']==401):
            raise tornado.web.HTTPError(401)
        raise tornado.web.HTTPError(500) class LectureHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum')
        data = {
            'Login.Token1':cardnum,
            'Login.Token2':self.get_argument('password'),
        }
        retjson = {'code':200, 'content':''}

        # read from cache
        try:
            status = self.db.query(LectureCache).filter( LectureCache.cardnum ==  cardnum ).one()
            if status.date > int(time()) - lectureCacheTime and status.text != '*':
                self.write(base64.b64decode(status.text))
                self.db.close()
                self.finish()
                return
        except NoResultFound:
            status = LectureCache(cardnum=cardnum, text='*', date=int(time()))
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()

        try:
            response = authApi(cardnum,self.get_argument('password'))
            if response['code']==200:
                cookie = response['content']
                client = AsyncHTTPClient()
                request = HTTPRequest(
                    LOGIN_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                cookie += ';' + response.headers['Set-Cookie'].split(';')[0]
                request = HTTPRequest(
                    USERID_URL,
                    method='GET',
                    headers={'Cookie':cookie},
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                soup = BeautifulSoup(response.body)
                userid = soup.findAll(attrs={"align": "left"})[2].text

                page = 1
                data = {
                    'account':userid,
                    'startDate':'',
                    'endDate':'',
                    'pageno':0
                }
                fliter = ['九龙湖', '手持考', '行政楼', '网络中', '机电大', '校医院', '研究生']
                lecture = []
                count = 0
                while 1:
                    data['pageno'] = page
                    request = HTTPRequest(
                        DATA_URL,
                        method='POST', 
                        body=urllib.urlencode(data),
                        headers={'Cookie':cookie},
                        request_timeout=TIME_OUT)
                    response = yield tornado.gen.Task(client.fetch, request)
                    soup = BeautifulSoup(response.body)
                    tr = soup.findAll('tr',{"class": re.compile("listbg")})
                    if not tr:
                        break
                    for td in tr:
                        td = td.findChildren()
                        if not td[4].text[:3].encode('utf-8') in fliter:
                            tmp = {}
                            datecheck = td[0].text.split(' ')[0]
                            if count>0 and datecheck == lecture[count-1]['date'].split(' ')[0]:
                                continue
                            tmp['date'] = td[0].text
                            tmp['place'] = td[4].text
                            lecture.append(tmp)
                            count += 1
                    page += 1
                retjson['content'] = {'count':count, 'detial':lecture}
            else:
                retjson['code'] = 401
                retjson['content'] = 'wrong card number or password'
        except Exception as e:
            print e
            retjson['code'] = 500
            retjson['content'] = 'error'
            if status.text!='*':
                self.write(base64.b64decode(status.text))
                self.finish()
                return
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()
            finally:
                self.db.remove()
        self.db.close() class LibAuthHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def on_finish(self):
        self.db.close()

    def get(self):

        cardnum = self.get_argument('cardnum', default=None)
        if not cardnum:
            # 因为需要返回图片，所以一卡通为空不做提示
            raise Exception
        try:
            client = HTTPClient()
            response = client.fetch(GET_CAPTCHA)
            cookie = response.headers['Set-Cookie'].split(';')[0]
            try:
                status = self.db.query(LibraryAuthCache).filter(LibraryAuthCache.cardnum == cardnum).one()
                status.cookie = cookie
                print status.cookie
            except NoResultFound:
                status = LibraryAuthCache(cardnum=cardnum, cookie=cookie, captcha='*', date=int(time()))
            self.db.add(status)
            try:
                self.db.commit()
            except Exception:
                self.db.rollback()
            self.set_header('Content-type', 'image/png')
            self.write(response.body)   # return captcha to client
        except Exception as e:
            self.write('error')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum', default=None)
        password = self.get_argument('password', default=None)
        captcha = self.get_argument('captcha', default=None)
        retjson = {'code': 200, 'content': ''}
        status = None
        if not (cardnum and password and captcha):
            retjson['code'] = 400
            retjson['content'] = 'parameters lack'
        else:
            # 直接从数据库读取cookie，不做try的尝试
            status = self.db.query(LibraryAuthCache).filter(LibraryAuthCache.cardnum == cardnum).one()
            cookie = status.cookie
            try:
                form_data = {
                    'number': cardnum,
                    'passwd': password,
                    'captcha': captcha,
                    'select': 'cert_no'
                }
                client = AsyncHTTPClient()
                request = HTTPRequest(
                    LOGIN_URL,
                    method='POST',
                    headers={'Cookie': cookie},
                    body=urllib.urlencode(form_data),
                    request_timeout=TIME_OUT
                    )
                response = yield tornado.gen.Task(client.fetch, request)
                soup = BeautifulSoup(response.body, 'html.parser')
                name = soup.findAll('font')[0].text
                if name:
                    retjson['code'] = 200
                    retjson['content'] = 'auth success'
                else:
                    retjson['code'] = 401
                    retjson['content'] = 'auth error'
            except Exception as e:
                retjson['code'] = 500
                retjson['content'] = 'error'
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        # refresh cache
        if (retjson['code'] == 200):
            status.password = password
            status.captcha = captcha
            status.date = int(time())
            self.db.add(status)
            try:
                self.db.commit()
            except Exception as e:
                self.db.rollback()
            finally:
                self.db.remove() class LibAuthCheckHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def on_finish(self):
        self.db.close()

    def get(self):
        self.write('herald web service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):

        cardnum = self.get_argument('cardnum')
        retjson = {'code': 200, 'content': ''}
        if not cardnum:
            retjson['code'] = 400
            retjson['content'] = u'parameters lack'
        else:
            try:
                status = self.db.query(LibraryAuthCache).filter(LibraryAuthCache.cardnum == cardnum).one()
                cookie = status.cookie
            except NoResultFound:
                cookie = '*'
                retjson['code'] = 401
                retjson['content'] = u'auth error'
            try:
                client = AsyncHTTPClient()
                request = HTTPRequest(
                        LOGIN_URL,
                        method='GET',
                        headers={'Cookie': cookie},
                        request_timeout=TIME_OUT
                        )
                response = yield tornado.gen.Task(client.fetch, request)
                soup = BeautifulSoup(response.body, 'html.parser')
                name = soup.findAll('font')[0].text
                if name:
                    retjson['content'] = u'auth success'
                    retjson['code'] = 200
                else:
                    retjson['code'] = 401
                    retjson['content'] = u'auth error'
            except Exception as e:
                retjson['code'] = 500
                retjson['content'] = u'error'
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish() class LibListHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def on_finish(self):
        self.db.close()

    def get(self):
        self.write('herald webservice')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum', default=None)
        password = self.get_argument('password', default=None)
        retjson = {'code': 200, 'content': ''}
        status = None
        if not (cardnum and password):
            retjson['code'] = 400
            retjson['content'] = 'parameters lack'
        else:
            # 直接从数据库读取cookie，不做try的尝试
            status = self.db.query(LibraryAuthCache).filter(LibraryAuthCache.cardnum == cardnum).one()
            cookie = status.cookie
            try:
                client = AsyncHTTPClient()
                request = HTTPRequest (
                    CAPTCHA_CRACK_URL,
                    method='GET',
                    request_timeout=TIME_OUT
                )
                response = yield tornado.gen.Task(client.fetch, request)
                crack = json.loads(response.body)
                captcha = crack['captcha']
                cookies = crack['cookies']
                form_data = {
                    'number': cardnum,
                    'passwd': password,
                    'captcha': captcha,
                    'select': 'cert_no'
                }
                request = HTTPRequest(
                    LOGIN_URL,
                    method='POST',
                    headers={'Cookie': cookies},
                    body=urllib.urlencode(form_data),
                    request_timeout=TIME_OUT
                    )
                response = yield tornado.gen.Task(client.fetch, request)
                soup = BeautifulSoup(response.body, 'html.parser')
                name = soup.findAll('font')[0].text
                if name:
                    retjson['code'] = 200
                    retjson['content'] = 'auth success'
                else:
                    retjson['code'] = 401
                    retjson['content'] = 'auth error'
            except Exception as e:
                retjson['code'] = 500
                retjson['content'] = 'error'
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        # refresh cache
        if (retjson['code'] == 200):
            status.password = password
            status.captcha = captcha
            status.date = int(time())
            self.db.add(status)
            try:
                self.db.commit()
            except Exception as e:
                self.db.rollback()
            finally:
                self.db.remove() class LibRenewHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def on_finish(self):
        self.db.close()

    def get(self):
        self.write("herald webservice")

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum')
        # captcha = self.get_argument('captcha')
        barcode = self.get_argument('barcode')
        retjson = {'code': 200, 'content': u''}
        if (not cardnum or not barcode):
            retjson['code'] = 400
            retjson['content'] = u'parameter lack'
        else:
            try:
                status = self.db.query(LibraryAuthCache).filter(LibraryAuthCache.cardnum == cardnum).one()
                if (status.cookie != '*'):
                    cookie = status.cookie
                    # 根据实验图书馆每次的验证码和登录验证码一致，
                    # 这里采用登录验证码，如发生变动，请自行修改
                    captcha = status.captcha
                else:
                    retjson['code'] = 401
                    retjson['content'] = u'auth error'
            except Exception as e:
                retjson['code'] = 500
                retjson['content'] = u'error'
            
            try:
                client = AsyncHTTPClient()
                request = HTTPRequest(
                    LOGIN_URL,
                    method='GET',
                    headers={'Cookie': cookie},
                    request_timeout=TIME_OUT
                    )
                response = yield tornado.gen.Task(client.fetch, request)
                soup = BeautifulSoup(response.body, 'html.parser')
                name = soup.findAll('font')[0].text
                if name:
                    flag = False
                    request = HTTPRequest(
                        LIST_URL,
                        method = 'GET',
                        headers={'Cookie': cookie},
                        request_timeout = TIME_OUT
                        )
                    response = yield tornado.gen.Task(client.fetch, request)
                    soup = BeautifulSoup(response.body, 'html.parser')
                    td = soup.findAll('td', {'class': 'whitetext'})
                    for i in range(0, len(td), 8):
                        if (barcode == td[i].text):
                            checkcode = td[i+7].input['onclick'].split('\'')[3]
                            request = HTTPRequest(
                                RENEW_URL%(barcode, checkcode, captcha, int(time()*1000)),
                                method='GET',
                                headers={'Cookie': cookie},
                                request_timeout=TIME_OUT
                                )
                            response = yield tornado.gen.Task(client.fetch, request)
                            if (response.body == 'invalid call'):
                                flag = False
                            else:
                                flag = True
                    if flag:
                        if u'wrong' in response.body:
                            retjson['code'] = 200
                            retjson['content'] = u'wrong captcha'
                        else:
                            soup = BeautifulSoup(response.body, 'html.parser')
                            retjson['code'] = 200
                            retjson['content'] = soup.findAll('font')[0].text
                    else:
                        retjson['code'] = 400
                        retjson['content'] = u'fail'
                else:
                    retjson['code'] = 401
                    retjson['content'] = u'auth error'
            except Exception as e:
                retjson['code'] = 500
                retjson['content'] = u'error'
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish() class HotHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db
    def on_finish(self):
        self.db.close()

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        HOT_URL = "http://www.libopac.seu.edu.cn:8080/top/top_lend.php"
        retjson = {
            'code':200,
            'content':''
        }
        try:
            status = self.db.query(LibraryHotCache).one()
            if status.date > int(time())-600000:
                self.write(base64.b64decode(status.text))
                self.db.close()
                self.finish()
                return
        except NoResultFound:
            status = LibraryHotCache(text='*', date=int(time()))

        try:
            client = AsyncHTTPClient()
            request = HTTPRequest(
                HOT_URL,
                method='GET',
                request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            soup = BeautifulSoup(response.body)
            td = soup.findAll('td', {'class': 'whitetext'})
            ret = []
            length = 80 if len(td)>80 else len(td)
            for i in range(0, length, 8):
                s = td[i+1].text.split('/')
                book = {
                    'name': self.entity_parser(td[i+1].text),
                    'author':self.entity_parser(td[i+2].text),
                    'count':td[i+6].text,
                    'place': self.entity_parser(td[i+4].text),
                }
                ret.append(book)
            retjson['content'] = ret
        except Exception,e:
            retjson['code'] = 500
            retjson['content'] = str(e)
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()

        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()
            finally:
                self.db.remove()

    def entity_parser(self, string):
        x = re.findall('&#x(.{4});', string)
        s = ''
        for c in x:
            s += unichr(int(c,16))
        return s class PCHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db
    def get(self):
        self.write('Herald Web Service')

    def post(self):
        retjson = {'code':200, 'content':u'暂时关闭'}
        try:
            if self.ismorning():
                status = self.db.query(PCCache).filter( PCCache.date == self.today(),PCCache.lastdate+180>int(time())).one()
                retjson['content'] = base64.b64decode(status.text)
                self.db.close()
                self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
                self.finish()
            else:
                status = self.db.query(PCCache).filter( PCCache.date == self.today()).one()
                retjson['content'] = base64.b64decode(status.text)
                self.db.close()
                self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
                self.finish()
        except NoResultFound:
            retjson['code'] = 201
            retjson['content'] = 'refreshing'
            self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
            self.finish()
            self.refresh_status()
        except Exception,e:
            # print traceback.print_exc()
            retjson['code'] = 500
            retjson['content'] = str(e)
            self.db.close()
            self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
            self.finish()

        

    def refresh_status(self):
        lock = self.db.query(PCCache).filter(
                    PCCache.date == 0).one()
        if lock.text == '1'or(lock.lastdate!=0 and lock.lastdate+180>int(time())):
            return
        else:
            lock.text == '1'
            lock.lastdate = int(time())
            self.db.commit()

        # ret = self.qq_request()
        ret = self.getData()
        if ret and (ret['code'] == 200):
            self.recognize1(ret['content'])
        lock.text == '0'
        self.db.commit()
        self.db.close()



    def getData(self):
        ret = {'code':200,'content':''}
        try:
            content = self.db.execute("select * from wechat.boardcast where date like '"+datetime.datetime.now().strftime("%Y-%m-%d")+"%%' order by mid DESC LIMIT 1").fetchall()
            if content:
                ret['content'] = content[0]['msg']
            else:
                ret['code'] = 400
        except Exception,e:
            ret['code'] = 500
        return ret

    def today(self):
        return int(strftime('%Y%m%d', localtime(time())))
    def ismorning(self):
        if int(strftime('%H', localtime(time())))==6:
            return True
        else:
            return False

    def recognize(self, text):
        y_keyword = [u'正常跑操', u'跑操正常', u'今天继续跑操', u'今天跑操']
        result = u'今天不跑操'
        for k in y_keyword:
            if text.find(k)>=0:
                result = u'今天正常跑操'
                break
        if self.ismorning():
            try:
                status = self.db.query(PCCache).filter(PCCache.date==self.today()).one()
                status.text = base64.b64encode(result)
                status.lastdate = int(time())
                self.db.add(status)
            except NoResultFound:
                status = PCCache(date=self.today(), text=base64.b64encode(result),lastdate=int(time()))
                self.db.add(status)
            except:
                pass
                # print traceback.print_exc()
        else:
            status = PCCache(date=self.today(), text=base64.b64encode(result),lastdate=int(time()))
            self.db.add(status)

        self.db.commit()

    def recognize1(self,text):
        y_keyword = [u'早操正常进行', u'正常', u'今天继续跑操', u'今天跑操']
        result = u'今天不跑操'
        for k in y_keyword:
            if text.find(k)>=0:
                result = u'今天正常跑操'
                break
        if self.ismorning():
            try:
                status = self.db.query(PCCache).filter(PCCache.date==self.today()).one()
                status.text = base64.b64encode(result)
                status.lastdate = int(time())
                self.db.add(status)
            except NoResultFound:
                status = PCCache(date=self.today(), text=base64.b64encode(result),lastdate=int(time()))
                self.db.add(status)
            except:
                pass
                # print traceback.print_exc()
        else:
            status = PCCache(date=self.today(), text=base64.b64encode(result),lastdate=int(time()))
            self.db.add(status)

        self.db.commit()

    pubKey=rsa.PublicKey(int(
        'F20CE00BAE5361F8FA3AE9CEFA495362'
        'FF7DA1BA628F64A347F0A8C012BF0B25'
        '4A30CD92ABFFE7A6EE0DC424CB6166F8'
        '819EFA5BCCB20EDFB4AD02E412CCF579'
        'B1CA711D55B8B0B3AEB60153D5E0693A'
        '2A86F3167D7847A0CB8B00004716A909'
        '5D9BADC977CBB804DBDCBA6029A97108'
        '69A453F27DFDDF83C016D928B3CBF4C7',
        16
    ), 3)
    def fromhex(self, s):
        return bytes(bytearray.fromhex(s))
    def pwdencode(self, vcode, uin, pwd):
        salt = uin.replace(r'\x', '')
        h1 = hashlib.md5(pwd.encode()).digest()
        s2 = hashlib.md5(h1 + self.fromhex(salt)).hexdigest().upper()
        rsaH1 = binascii.b2a_hex(rsa.encrypt(h1, self.pubKey)).decode()
        rsaH1Len = hex(len(rsaH1) // 2)[2:]
        hexVcode = binascii.b2a_hex(vcode.upper().encode()).decode()
        vcodeLen = hex(len(hexVcode) // 2)[2:]
        l = len(vcodeLen)
        if l < 4:
            vcodeLen = '0' * (4 - l) + vcodeLen
        l = len(rsaH1Len)
        if l < 4:
            rsaH1Len = '0' * (4 - l) + rsaH1Len
        pwd1 = rsaH1Len + rsaH1 + salt + vcodeLen + hexVcode
        saltPwd = base64.b64encode(
            tea.encrypt(self.fromhex(pwd1), self.fromhex(s2))
        ).decode().replace('/', '-').replace('+', '*').replace('=', '_')
        return saltPwd
    def qq_request(self):
        retjson = {'code':400,'content':'No Result'}
        try:
            client = HTTPClient()
#init
            request = HTTPRequest(
                init_url,
                method='GET',
                headers={
                    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36',
                    'Accept-Encoding': 'gzip, deflate',
                    'Cookie':'',
                    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
                },
                request_timeout=4
                )
            response = client.fetch(request)
            init_cookie = response.headers['Set-Cookie']
#check
            request = HTTPRequest(
                checkurl,
                method='GET',
                headers={
                    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36',
                    'Accept-Encoding': 'gzip, deflate',
                    'Cookie':init_cookie,
                    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
                },
                request_timeout=4
                )
            response = client.fetch(request)
            check_cookie = response.headers['Set-Cookie']

            result = response.body.split('\'')
           
#login
            
            session = result[7]
            code = result[3]
            salt = result[5]
            data = {
                'aid':'549000929',
                'daid':'147',
                'device':2,
                'fp':'loginerroralert',
                'from_ui':1,
                'g':1,
                'h':1,
                'low_login_enable':0,
                'p':self.pwdencode(code,salt,password),
                'pt_3rd_aid':0,
                'pt_randsalt':0,
                'pt_uistyle':9,
                'pt_vcode_v1':0,
                'pt_verifysession_v1':session,
                'ptlang':2052,
                'ptredirect':1,
                'u':username,
                'u1':'http://m.qzone.com/infocenter?g_f=',
                'verifycode':code
            }

            request = HTTPRequest(
                login_url+urllib.urlencode(data),
                method='GET',
                headers={
                    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36',
                    'Accept-Encoding': 'gzip, deflate',
                    'Cookie':init_cookie+check_cookie,
                    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
                },
                request_timeout=4
                )
            response = client.fetch(request)
            # print response.body
#get_token
            fuckcookie = response.headers['Set-Cookie']
            temp = fuckcookie.split(';')
            
            pt2gguin = temp[0]+';'
            skey = temp[7].split(',')[1]+';'
            ptcz = temp[28].split(',')[1]+';'
            uin = temp[4].split(',')[1]+';'
            ptsip = temp[22].split(',')[1]+';'

            tempcookie = pt2gguin+skey+ptcz+uin+ptsip
            getPtSkeyUrl = response.body.split('\'')[5]
# get superkey
            request1 = HTTPRequest(
                getPtSkeyUrl,
                method="GET",
                headers={
                    'Cookie':init_cookie+tempcookie+fuckcookie,
                },
                request_timeout = 8,
                follow_redirects=False
            )

            ptskey = ""
            try:
                response = client.fetch(request1)
            except HTTPError as e:
                fuckfuckcookie = e.response.headers['Set-Cookie']
                fuckcookieTemp = fuckfuckcookie.split(';')
                ptskey = fuckcookieTemp[13].split('=')[1]
            hash1 = 5381
            for i in ptskey:
                hash1 +=(hash1<<5)+ord(i)
            super_token = hash1&2147483647


            jsonUrl = 'http://m.qzone.com/combo?g_tk='+str(super_token)+'&hostuin=3084772927&action=1&g_f=&refresh_type=1&res_type=2&format=json'#refresh_type确定说说条数
            finalUrl = 'http://m.qzone.com/infocenter#3084772927/mine'
            request = HTTPRequest(
                jsonUrl,
                method='GET',
                headers={
                    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36',
                    'Accept-Encoding': 'gzip, deflate',
                    'Cookie':init_cookie+fuckcookie+fuckfuckcookie,
                    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
                },
                request_timeout=4
                )
            response = client.fetch(request)
            ret = json.loads(response.body)
            testjson = ret['data']['feeds']['vFeeds']
            re_regular = re.compile("\[em\]e(\d+)\[\/em\]")

            for i in range(len(testjson)):
                try:
                    content =  testjson[i]['summary']['summary']
                    c_time = testjson[i]['comm']['time']
                    # print re_regular.sub('',content)
                    if u'跑操早播报' in content:
                        if strftime("%Y-%m-%d",localtime(c_time)) == strftime("%Y-%m-%d",localtime(time())):
                            if strftime("%H",localtime(c_time))== '06':
                                retjson['code'] = 200
                                retjson['content'] =  testjson[i]['summary']['summary'][7:]
                                # retjson['content'] =  re_regular.sub('',testjson[i]['summary']['summary'])
                except KeyError:
                    pass
        except Exception,e:
            # print traceback.print_exc()
            retjson['code'] = 201
            retjson['content'] = str(e)
        return retjson class JWCHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write("hello")
    def on_finish(self):
        self.db.close()

    def post(self):
        retjson = {'code':200, 'content':''}
        try:
            status = self.db.query(JWCCache).filter( JWCCache.date > int(time())-jwcCacheTime).order_by(JWCCache.date.desc()).all()
	    if len(status) == 0:
		raise NoResultFound
	    status = status[0]
            self.write(base64.b64decode(status.text))
            self.finish()
            return
        except NoResultFound:
            ret = self.refresh_status()
            if ret['code'] == 200:
                ret = json.dumps(ret, ensure_ascii=False, indent=2)
                status = JWCCache(date=int(time()), text=base64.b64encode(ret))
                self.db.add(status)
                self.db.commit()
                self.write(ret)
                self.finish()
                return
            else:
                retjson['code'] = 201
                retjson['content'] = 'refresh'
        except Exception,e:
            retjson['code'] = 500
            retjson['content'] = "error:"+str(e)
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()


    def refresh_status(self):
        try:
            lock = self.db.query(JWCCache).filter(
                        JWCCache.date == 0).one()
        except NoResultFound:
            lock = JWCCache(date=0, text='0')
            self.db.add(lock)
        if lock.text == '1':
            return {'code':201}
        else:
            lock.text == '1'
            self.db.commit()
        ret = self.parser()
        lock.text == '0'
        self.db.commit()
        return ret

    def today(self):
        return int(strftime('%Y%m%d', localtime(time())))

    def parser(self):
        retjson = {'code':200,'content':''}
        header = { 
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Encoding': 'gzip, deflate, sdch',
            'Accept-Language': 'zh-CN,zh;q=0.8',
            'Host':'jwc.seu.edu.cn',
            'Connection':'keep-alive',
            'Upgrade-Insecure-Requests':'1'
        }
        try:
            client = HTTPClient()
            request = HTTPRequest(JWC_URL, method='GET',headers=header,request_timeout=TIME_OUT)
            response = client.fetch(request)
            html = response.body
            soup = BeautifulSoup(html)
            items = soup.findAll('table', {'width':"100%"})
            info = {
                '最新动态': self.abstract(items[12:17],1), 
                '教务信息': self.abstract(items[34:34+7],0), 
                '学籍管理': self.abstract(items[45:45+7],0), 
                '实践教学': self.abstract(items[56:56+7],0), 
                '合作办学': self.abstract(items[67:67+4],0),
                }
            retjson = {'code':200, 'content':info}
        except:
            retjson['code'] = 400
            # print traceback.print_exc()
        return retjson

    def abstract(self, tag, x):
        abst = []
        for t in tag:
            if 1:
                if x:
                    abst.append({
                        'title': t.a.attrs[2][1],
                        'href': JWC_URL+t.a.attrs[0][1],
                        'date': t.div.text,
                        })
                else:
                    abst.append({
                        'title': t.a.attrs[2][1],
                        'href': JWC_URL+t.a.attrs[0][1],
                        'date': str(t)[-36:-26],
                        })
            #except:
            #    pass
        return abst class SchoolBusHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.init_db()
        #self.write('Herald Web Service')

    def post(self):
        try:
            data = self.db.query(DataCache).filter( DataCache.key == 10001 ).one()
            self.write(base64.b64decode(data.data))
            self.db.close()
            self.finish()
        except:
            self.init_db()
            data = self.db.query(DataCache).filter( DataCache.key == 10001 ).one()
            self.write(base64.b64decode(data.data))
            self.db.close()
            self.finish()

    def init_db(self):
        bus_json = {
            "weekend":{
                "前往地铁站":[
                    { "time":"8:00-9:30", "bus":"每 30min 一班"},
                    { "time":"9:30-11:30", "bus":"每 1h 一班"},
                    { "time":"11:30-13:00", "bus":"每 30min 一班"},
                    { "time":"13:30-16:30", "bus":"每 1h 一班"},
                    { "time":"17:00-19:00", "bus":"每 30min 一班"},
                    { "time":"19:00-22:00", "bus":"每 1h 一班"}
                ],
                "返回九龙湖":[
                    { "time":"8:00-9:30", "bus":"每 30min 一班"},
                    { "time":"9:30-11:30", "bus":"每 1h 一班"},
                    { "time":"11:30-13:00", "bus":"每 30min 一班"},
                    { "time":"13:30-16:30", "bus":"每 1h 一班"},
                    { "time":"17:00-19:00", "bus":"每 30min 一班"},
                    { "time":"19:00-22:00", "bus":"每 1h 一班"}
                ]
            },
            "weekday":{
                "前往地铁站":[
                    { "time":"7:10-10:00", "bus":"每 10min 一班"},
                    { "time":"10:00-11:30", "bus":"每 30min 一班"},
                    { "time":"11:30-13:30", "bus":"每 10min 一班"},
                    { "time":"13:30-15:00", "bus":"13:30,14:00"},
                    { "time":"15:00-15:50", "bus":"每 10min 一班"},
                    { "time":"16:00-17:00", "bus":"16:00"},
                    { "time":"17:00-18:30", "bus":"每 10min 一班"},
                    { "time":"18:30-22:00", "bus":"每 30min 一班(20:30没有班车)"}
                ],
                "返回九龙湖":[
                    { "time":"7:10-10:00", "bus":"每 10min 一班"},
                    { "time":"10:00-11:30", "bus":"每 30min 一班"},
                    { "time":"11:30-13:30", "bus":"每 10min 一班"},
                    { "time":"13:30-15:00", "bus":"13:30,14:00"},
                    { "time":"15:00-15:50", "bus":"每 10min 一班"},
                    { "time":"16:00-17:00", "bus":"16:00"},
                    { "time":"17:00-18:30", "bus":"每 10min 一班"},
                    { "time":"18:30-22:00", "bus":"每 30min 一班(20:30没有班车)"}
                ]
            }

        }
        retjson = {'code': 200, 'content': bus_json}
        try:
            data = self.db.query(DataCache).filter( DataCache.key == 10001 ).one()
            data.data = base64.b64encode(json.dumps(retjson, ensure_ascii=False, indent=2))
        except NoResultFound:
            data = DataCache(key=10001, data=base64.b64encode(json.dumps(retjson, ensure_ascii=False, indent=2)))
        self.db.add(data)
        self.db.commit() class NewSchoolBusHandler(tornado.web.RequestHandler):

        @tornado.web.asynchronous
        @tornado.gen.engine
        def post(self):
            try:
                client = AsyncHTTPClient()
                request = HTTPRequest('http://121.248.63.119/busservice/lines')
                response = yield tornado.gen.Task(client.fetch, request)
                lines = json.loads(response.body)['data']['lines']

                for line in lines:
                    line_id = line['id']
                    request = HTTPRequest('http://121.248.63.119/busservice/queryBus?lineId=' + str(line_id))
                    response = yield tornado.gen.Task(client.fetch, request)
                    buses = json.loads(response.body)
                    line['buses'] = buses['data']['buses']

                    request = HTTPRequest('http://121.248.63.119/busservice/lineDetail?lineId=' + str(line_id))
                    response = yield tornado.gen.Task(client.fetch, request)
                    detail = json.loads(response.body)
                    line['stops'] = detail['data']['line']['linePoints']

                self.write(json.dumps({ 'code': 200, 'content': lines }, ensure_ascii=False))
            except:
                self.write(json.dumps({ 'code': 400, 'content': [] }, ensure_ascii=False))
            self.finish() class PhylabHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        number = self.get_argument('number',default=None)
        password = self.get_argument('password',default=None)
        term = self.get_argument('term',default=None)

        retjson = {'code':200, 'content':''}
        if not number or not password or not term:
            retjson['code'] = 400
            retjson['content'] = 'params lack'
        else:
            # read from cache
            try:
                status = self.db.query(PhylabCache).filter( PhylabCache.cardnum ==  number ).one()
                if status.date > int(time())-phylabCacheTime and status.text != '*':
                    self.write(base64.b64decode(status.text))
                    self.db.close()
                    self.finish()
                    return
            except NoResultFound:
                status = PhylabCache(cardnum=number, text='*', date=int(time()))
                self.db.add(status)
                try:
                    self.db.commit()
                except:
                    self.db.rollback()

            if int(term[3:5]) - int(number[3:5]) == 1:
                curType = cur_type_up
                retjson['content'] = {'基础性实验(上)':[],'基础性实验(上)选做':[],'文科及医学实验':[],'文科及医学实验选做':[]}
            else:
                curType = cur_type_down
                retjson['content'] = {'基础性实验(下)':[],'基础性实验(下)选做':[],'文科及医学实验':[],'文科及医学实验选做':[]}

            client = AsyncHTTPClient()
            loginValues['ctl00$cphSltMain$UserLogin1$txbUserCodeID'] = number
            loginValues['ctl00$cphSltMain$UserLogin1$txbUserPwd'] = password

            try:
                request = HTTPRequest(
                        LOGIN_URL,
                        method='GET',
                        request_timeout=TIME_OUT
                    )
                response = yield tornado.gen.Task(client.fetch, request)
                self.init_data(response.body)
                header['Cookie'] = response.headers['Set-Cookie'].split(';')[0]
                request = HTTPRequest(
                        LOGIN_URL,
                        method='POST',
                        headers = header,
                        body = urllib.urlencode(loginValues),
                        request_timeout=TIME_OUT
                    )
                response = yield tornado.gen.Task(client.fetch, request)
                header['Cookie'] += ';'+response.headers['Set-Cookie'].split(';')[0]
                self.init_select_data(header['Cookie'])
                for curNumber in curType:
                    selectData['ctl00$cphSltMain$ShowAStudentScore1$ucDdlCourseGroup$ddlCgp'] = curNumber
                    getRequest =HTTPRequest(
                            phyLabCurUrl,
                            body=urllib.urlencode(selectData),
                            method='POST',
                            headers = header,
                            request_timeout=TIME_OUT
                        )
                    getResponse = yield tornado.gen.Task(client.fetch, getRequest)
                    retjson['content'][curType.get(curNumber)] = self.getCur(getResponse.body)
	    except KeyError:
                retjson = {
                    'code':200,
                    'content':{}
                }
            except Exception,e:
                retjson['code'] = 500
                retjson['content'] = 'error'
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        #refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()
            finally:
                self.db.remove()
        self.db.close()
            

    def getCur(self,html):
        dealSoup = BeautifulSoup(str(html))
        curTable = dealSoup.find('table',id="ctl00_cphSltMain_ShowAStudentScore1_gvStudentCourse")
        if curTable==None:
            return ''
        else:
            ret_content = []
            content = curTable.findAll('span')
            length = len(content)
            temp = {
                'name':'',
                'Date':'',
                'Day':'',
                'Teacher':'',
                'Address':'',
                'Grade':''
            }
            k = length/6
            for i in range(k):
                index = i*6
                temp = {
                'name':content[index].string,
                'Date':content[index+2].string,
                'Day':content[index+3].string,
                'Teacher':content[index+1].string,
                'Address':content[index+4].string,
                'Grade':content[index+5].string
                }
                ret_content.append(temp)
        return ret_content

    def init_data(self,body):
        try:
            content = BeautifulSoup(body)
            viewstate_value = content.find('input',{'id':'__VIEWSTATE'})
            EVENTVALIDATION = content.find('input',{'id':'__EVENTVALIDATION'})
            loginValues['__VIEWSTATE'] = viewstate_value['value']
            loginValues['__EVENTVALIDATION'] = EVENTVALIDATION['value']
        except:
            pass

    def init_select_data(self,cookie):
        try:
            client = HTTPClient()
            request = HTTPRequest(
                SELECTURL,
                method = "GET",
                headers = header,
                request_timeout=TIME_OUT
                )
            response = client.fetch(request)
            content = BeautifulSoup(response.body)
            viewstate_value = content.find('input',{'id':'__VIEWSTATE'})
            EVENTVALIDATION = content.find('input',{'id':'__EVENTVALIDATION'})
            selectData['__VIEWSTATE'] = viewstate_value['value']
            selectData['__EVENTVALIDATION'] = EVENTVALIDATION['value']
        except Exception,e:
            pass
 class CommonQueryHandler(tornado.web.RequestHandler):

    def get(self, campus, week, date, start_lesson, end_lesson):
        # filter paramter
        filter_result = filter_common(campus, week, date, start_lesson, end_lesson)

        if filter_result is None:
            self.write(json.dumps(['BAD_PARAMETER'], ensure_ascii=False))
        else:
            # access db
            result = get_free_classrooms(
                filter_result[0], filter_result[1], filter_result[2], filter_result[3], filter_result[4])
            self.write(json.dumps(result, ensure_ascii=False))

        self.finish() class QuickQueryHandler(tornado.web.RequestHandler):

    def get(self, campus, today_or_tomorrow, start_lesson, end_lesson):
        filter_result = filter_quick(
            campus, today_or_tomorrow, start_lesson, end_lesson)

        if filter_result is None:
            self.write(json.dumps(['BAD_PARAMETER'], ensure_ascii=False))
        else:
            # access db
            result = get_free_classrooms(
                filter_result[0], filter_result[1], filter_result[2], filter_result[3], filter_result[4])
            
            self.write(json.dumps(result, ensure_ascii=False))

        self.finish() class NewHandler(tornado.web.RequestHandler):
    def post(self):
        ret = {'code':200,'content':''}
        try:
            url = self.get_argument("url",None)
            method = self.get_argument("method",None)
            data = self.get_argument("data",None)
            if not (url and method):
                ret['code'] = 400
                ret['content'] = u'参数缺少'
            else:
                client = HTTPClient()
                request = HTTPRequest(
                    url = url, 
                    method = method
                    )
                if(method=="POST"):
                    request.body = urllib.urlencode(json.loads(data))
                response = client.fetch(request)
                ret['content'] = json.loads(response.body)
        except Exception,e:
            ret['code'] = 500
            ret['content'] = u'系统错误'
        self.write(json.dumps(ret,ensure_ascii=False, indent=2)) class NewNewHandler(tornado.web.RequestHandler):

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        ret = { 'code': 200, 'content': '' }
        try:
            campus_id = self.get_argument('campusId', default='22')
            date = self.get_argument('date')
            building_id = self.get_argument('buildingId', default='')
            start_sequence = self.get_argument('startSequence')
            end_sequence = self.get_argument('endSequence')
            page = self.get_argument('page', default='1')
            page_size = self.get_argument('pageSize', default='10')
            
            client = AsyncHTTPClient()
            request = HTTPRequest('http://58.192.114.179/classroom/common/getdateofweek?date=' + date)
            response = yield tornado.gen.Task(client.fetch, request)
            date_info = json.loads(response.body)
            
            request = HTTPRequest('http://58.192.114.179/classroom/show/getemptyclassroomlist', 
                                  method='POST', 
                                  body=urllib.urlencode({
                                      'pageNo': page,
                                      'pageSize': page_size,
                                      'campusId': campus_id,
                                      'buildingId': building_id,
                                      'startWeek': date_info['week'],
                                      'endWeek': date_info['week'],
                                      'dayOfWeek': date_info['dayOfWeek'],
                                      'startSequence': start_sequence,
                                      'endSequence': end_sequence,
                                      'termId': date_info['termId']
                                  }))
            response = yield tornado.gen.Task(client.fetch, request)
            ret['content'] = json.loads(response.body)
        except Exception,e:
            print e
            ret['code'] = 500
            ret['content'] = 'error'
            traceback.print_exc(e)
        self.write(json.dumps(ret,ensure_ascii=False, indent=2))
        self.finish() class LectureNoticeHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write('Herald Web Service')

    def post(self):
        retjson = {'code':500, 'content':u'暂无'}
        date = mktime(strptime(strftime('%Y-%m-%d' ,localtime(time())), '%Y-%m-%d'))

        # read from db
        try:
            status = self.db.query(LectureDB).filter( LectureDB.date >=  date ).all()
            if len(status) > 0:
                ret = []
                for l in status:
                    ret.append({
                        'date': l.time,
                        'topic': l.topic,
                        'speaker': l.speaker,
                        'location': l.location,
                        'detail': l.detail
                        })
                retjson['code'] = 200
                retjson['content'] = ret
        except NoResultFound:
            pass

        
        retjson = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(retjson)
        self.finish()
        self.db.close() class UserHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def on_finish(self):
        self.db.close()

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        _number = self.get_argument('number')
        retjson = {'code':500, 'content':''}

        try:
            now = int(time.time())
            user = self.db.query(UserDetail).filter(_number == UserDetail.cardnum).one()
            if ((user.last_update != None) and (now - user.last_update) < userCacheTime):
                # 存在缓存且缓存日期很新
                retjson['code'] = 200
                retjson['content'] = {
                        'cardnum': user.cardnum,
                        'schoolnum': user.schoolnum,
                        'name': user.name,
                        'sex': user.sex,
                        }
            else:
                # 兼容老版本不存在last_update字段
                # 更新缓存
                user.name, user.schoolnum, user.cardnum = self.get_schoolnum_name(_number)
                user.last_update = int(time.time())
                retjson['code'] = 200
                retjson['content'] = {
                        'cardnum': user.cardnum,
                        'schoolnum': user.schoolnum,
                        'name': user.name,
                        'sex': user.sex,
                        }
                self.db.add(user)
                self.db.commit()
            self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
            self.finish()
            return
        except NoResultFound as e:
            pass


        _user = self.get_schoolnum_name(_number)
        if (_user != "-1"):
            _name, _schoolnum, _cardnum = _user
            retjson['content']= {
                    'schoolnum': _schoolnum,
                    'cardnum': _cardnum,
                    'name': _name
                    }
            retjson['code'] =200
            user_detail = UserDetail(schoolnum = _schoolnum,  cardnum= _cardnum, name = _name, last_update = int(time.time()))
            self.db.add(user_detail)
            self.db.commit();
        else:
            pass
        self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()
        return

    def get_schoolnum_name(self, number):
        try:
            CURR_URL = 'http://xk.urp.seu.edu.cn/jw_service/service/stuCurriculum.action'
            term = "16-17-1"
            params = urllib.urlencode({
                'queryStudentId': number,
                'queryAcademicYear': term})
            client = HTTPClient()
            request = HTTPRequest(
                    CURR_URL,
                    method='POST',
                    body=params,
                    request_timeout=TIME_OUT)
            response = client.fetch(request)
            body = response.body
            if not body:
                return "-1"
            else:
                soup = BeautifulSoup(body)
                number = soup.findAll('td', align='left')[2].text[3:]
                name = soup.findAll('td', align='left')[4].text[3:]
                cardnum = soup.findAll('td', align='left')[3].text[5:]
                return name, number, cardnum
        except Exception,e:
            return "-1" class RoomHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def get(self):
        self.write('Herald Web Service')

    def on_finish(self):
        self.db.close()
    
    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        number = self.get_argument('number',default=None)
        retjson = {'code':200, 'content':''}
        data = {
            'Login.Token1':number,
            'Login.Token2':self.get_argument('password'),
        }

        # read from cache
        try:
            status = self.db.query(RoomCache).filter(RoomCache.cardnum == number).one()
            #if status.date > int(time())-600 and status.text != '*':
	    if status.text != '*':
                self.write(base64.b64decode(status.text))
                self.finish()
                return
        except NoResultFound:
            status = RoomCache(cardnum = number,text = '*',date = int(time()))
            self.db.add(status)
            try:
                self.db.commit()
            except:
                self.db.rollback()

        try:
            client = AsyncHTTPClient()
            response = authApi(number,self.get_argument("password"))
            
            if response['code'] == 200:
                cookie = response['content']
                request = HTTPRequest(
                    URL,
                    method='GET',
                    headers={'Cookie': cookie},
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                soup = BeautifulSoup(response.body)
                table2 = soup.findAll('td')
                room = table2[9].text
                bed = table2[10].text
                retjson['code'] = 200
                retjson['content'] = {
                    'bed': bed,
                    'room': room
                }
            else:
                retjson['code'] = 401
        except Exception,e:
            retjson['code'] = 200
	    retjson['content']={"bed":"","room":""}
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()

        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except Exception,e:
                self.db.rollback()
            finally:
                self.db.remove() class ExamHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db
    def on_finish(self):
        self.db.close()

    def get(self):
        self.write('Herald Web Service')

    @tornado.gen.engine
    def post(self):
        number = self.get_argument('cardnum',default=None)
        password = self.get_argument('password')
        retjson = {'code':200, 'content':''}
        # read from cache
        try:
            status = self.db.query(ExamCache).filter(ExamCache.cardnum == number).one()
            if status.date > int(time())-examCacheTime and status.text != '*':
                self.write(base64.b64decode(status.text))
                self.finish()
                return
        except NoResultFound:
            status = ExamCache(cardnum = number,text = '*',date = int(time()))
            self.db.add(status)
        try:
            self.db.commit()
        except:
            self.db.rollback()
        retjson = yield tornado.gen.Task(self.jwcHandler,number,password)
        ret = json.dumps(retjson, ensure_ascii=False, indent=2)
        self.write(ret)
        self.finish()
        # refresh cache
        if retjson['code'] == 200:
            status.date = int(time())
            status.text = base64.b64encode(ret)
            self.db.add(status)
            try:
                self.db.commit()
            except Exception,e:
                self.db.rollback()
            finally:
                self.db.remove()
    @tornado.web.asynchronous
    @tornado.gen.engine
    def newSeuHandler(self,number,password,callback=None):
        retjson = {'code':200, 'content':''}
        try:
            client = AsyncHTTPClient()
            response = authApi(number,password)
            if response['code'] == 200:
                header['Cookie'] = response['content']
                request = HTTPRequest(
                    FIRST_URL,
                    method="GET",
                    headers = header,
                    request_timeout=TIME_OUT
                )
                response = yield tornado.gen.Task(client.fetch,request)
                header['Cookie'] = header['Cookie'].split(';')[0]+';'+response.headers['Set-Cookie']
                request = HTTPRequest(
                    DETAIL_URL,
                    method="GET",
                    headers = header,
                    request_timeout=TIME_OUT
                )
                response = yield tornado.gen.Task(client.fetch,request)
                retjson['content'] = self.dealData(response.body)
            else:
                retjson['code'] = 408
        except IndexError:
            retjson['code'] = 200
            retjson['content'] = u'当前不在考试周'
        except Exception,e:
            retjson['code'] = 500
        callback(retjson)
    def dealData(self,content):
        content = BeautifulSoup(str(content))
        Table = content.findAll('table',{'class':'portlet-table'})[0]
        tr = Table.findAll('tr')
        ret = []
        length = len(tr) 
        if length == 1:
            return ret
        else:
            for i in range(1,length):
                td = tr[i].findAll('td')
                print td
                retTemp = {
                    'course':td[2].text,
                    'type':"",
                    'teacher':td[3].text,
                    'time':td[4].text,
                    'location':td[5].text,
                    'hour':td[6].text
                }
                ret.append(retTemp)
        return ret
    @tornado.web.asynchronous
    @tornado.gen.engine
    def jwcHandler(self,number,password,callback=None):
        retjson = {'code':200, 'content':''}
        try:
            client = AsyncHTTPClient()
            request = HTTPRequest(VERCODE_URL, request_timeout=TIME_OUT)
            response = yield tornado.gen.Task(client.fetch, request)
            if not response.headers:
                retjson['code'] = 408
                retjson['content'] = 'time out'
            else:
                cookie = response.headers['Set-Cookie'].split(';')[0]#+";"+response.headers['Set-Cookie'].split(';')[1].split(',')[1]
                img = Image.open(io.BytesIO(response.body))
                vercode = self.recognize(img)
                params = urllib.urlencode({
                    'userName': number,
                    'password': password,
                    'vercode': vercode
                })
                request = HTTPRequest(LOGIN_URL, body=params, method='POST',
                    headers={'Cookie': cookie},
                    request_timeout=TIME_OUT)
                response = yield tornado.gen.Task(client.fetch, request)
                if not response.headers:
                    retjson['code'] = 408
                    retjson['content'] = 'time out'
                else:
                    if 'vercode' in str(response.body):
                        retjson['code'] = 401
                        retjson['content'] = 'wrong card number or password'
                    else:
                        request = HTTPRequest(INFO_URL,
                            request_timeout=TIME_OUT,
                            headers={'Cookie': cookie})
                        response = yield tornado.gen.Task(client.fetch, request)
                        if not response.headers:
                            retjson['code'] = 408
                            retjson['content'] = 'time out'
                        else:
                            retjson['content'] = self.parser(response.body)
        except Exception,e:
            retjson['code'] = 500
            retjson['content'] = str(e)
        callback(retjson)
    def parser(self,content):
        content = BeautifulSoup(str(content))
        Table = content.findAll('table',{'id':'table2'})[0]
        tr = Table.findAll('tr')
        ret = []
        length = len(tr) 
        if length == 1:
            return ret
        else:
            for i in range(1,length):
                td = tr[i].findAll('td')
                retTemp = {
                    'course':td[3].text,
                    'type':td[4].text,
                    'teacher':td[5].text[:-6],
                    'time':td[6].text[:-6],
                    'location':td[7].text,
                    'hour':td[8].text
                }
                ret.append(retTemp)
        return ret

    def recognize(self, img):
        start = [13, 59, 105, 151]
        result = ''
        for i in start:
            sample = []
            for i in xrange(i, i + 40):
                temp = 0
                for j in xrange(0, 100):
                    temp += (img.getpixel((i, j))[1] < 40)
                sample.append(temp)
            min_score = 1000
            max_match = 0
            for idx, val in enumerate(STANDARD):
                diff = []
                for i in xrange(len(sample)):
                    diff.append(sample[i] - val[i])
                avg = float(sum(diff)) / len(diff)

                for i in xrange(len(sample)):
                    diff[i] = abs(diff[i] - avg)
                score = sum(diff)
                if score < min_score:
                    min_score = score
                    max_match = idx

            result = result + str(max_match)
        return result class YuyueHandler(tornado.web.RequestHandler):

    @property
    def db(self):
        return self.application.db

    def on_finish(self):
        self.db.close()

    def get(self):
        self.write('Herald Web Service')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):
        cardnum = self.get_argument('cardnum')
        password = self.get_argument('password')
	method_type = self.get_argument('method')
        retjson = {'code':200, 'content':''}
        try:
            if method_type not in method.keys():
                retjson['code'] = 500
                retjson['content'] = 'method is not allowed'
            else:
                cookie = getCookie(self.db,cardnum,password)
                if cookie['code'] == 200:
                    meth = method[method_type]
                    data = []
                    for i in meth['param']:
                        if method_type=='new' and i=='useUserIds':
                            ar = json.loads(self.get_argument(i))
			    user = ''
                            for j in ar:
				user+=j+','
                            data.append((i,user))
			elif i=='orderVO.useMode':
                            data.append((i,{'1':2,'2':1}[self.get_argument(i)]))
                        else:
                            data.append((i,self.get_argument(i)))
		    # temp ignore judge
                    if method_type == "judgeOrder":
                        retjson['content'] = {'msg':'ok','code':0}
                    else:
                        retjson['content'] = self.getData(meth['url'],meth['method'],data,cookie['content'])
                    #retjson['content'] = self.getData(meth['url'],meth['method'],data,cookie['content'])
                else:
                    retjson['code'] = 408
                    retjson['content'] = 'cookie can not get'
        except MissingArgumentError:
            retjson['code'] = 400
            retjson['content'] = u'参数缺少'
        except Exception,e:
	    retjson['code'] = 500
            retjson['content'] = str(e)
	    
	self.write(json.dumps(retjson, ensure_ascii=False, indent=2))
        self.finish()


    def getData(self,url,method,data,cookie):
        try:
            client = HTTPClient()
            request = HTTPRequest(
                    url,
                    method=method,
                    headers={
                        'Cookie':cookie
                    }
                )
            if data and method=="GET":
                url = url_concat(url,data)
                url = url.replace("+","%20")
                request.url = url
            elif data and method=="POST":
                realData = {}
                for i in data:
                    realData[i[0]] = i[1]
                data = urllib.urlencode(realData)
                request.body = data
            response = client.fetch(request)
            return json.loads(response.body)
        except Exception,e:
            # print str(e)
            #traceback.print_exc()
            return str(e) class LogHandler(tornado.web.RequestHandler):
    """
        本模块为日志分析后端模块, 预先分析好的日志先存储于数据库中,
        使用时读取数据库中的json信息, 做简单处理后返回
    """
    def get(self):
        self.write('herald webservice')

    def post(self):
        retjson = {'code': '200', 'content': 'None'}

        date_start = self.get_argument('date_start', default='unsolved')
        date_cnt = int(self.get_argument('date_cnt', default='1'))

        content = []
        try:
            log_list = self.db.query(DayLogAnalyze).\
                    order_by(DayLogAnalyze.date).\
                    filter(DayLogAnalyze.date >= date_start).\
                    limit(date_cnt).all()

            if log_list:
                for i in range(date_cnt):
                    content_item = dict()
                    log = log_list[i]
                    content_item['date'] = eval(log.date)
                    content_item['every_hour_count'] = eval(log.every_hour_count)
                    content_item['api_order'] = eval(log.api_order)
                    content_item['device_distribute'] = eval(log.device_distribute)
                    content_item['call_count'] = log.call_count
                    content_item['ios_version'] = eval(log.ios_version)
                    content_item['android_version'] = eval(log.android_version)

                    content.append(content_item)

        except Exception as e:
            retjson['code'] = 500
            retjson['content'] = 'error'
            print e

        retjson['code'] = 200
        retjson['content'] = content
        self.write(json.dumps(retjson, indent=2, ensure_ascii=False))
from sqlalchemy.orm import scoped_session, sessionmaker
from mod.models.db import engine
from mod.curriculum.term_handler import TermHandler
from mod.curriculum.sidebar_handler import SidebarHandler
from mod.curriculum.curriculum_handler import CurriculumHandler
from mod.simsimi.handler import SIMSIMIHandler
from mod.gpa.gpa_handler import GPAHandler
from mod.pe.handler import PEHandler,ticeInfoHandler
from mod.pe.pedetailHandler import pedetailHandler
from mod.srtp.srtp_handler import SRTPHandler
from mod.card.handler import CARDHandler
from mod.nic.handler import NICHandler
from mod.auth.handler import AuthHandler
from mod.lecture.handler import LectureHandler
from mod.library.library_auth import LibAuthHandler
from mod.library.library_auth_check import LibAuthCheckHandler
from mod.library.listhandler import LibListHandler
from mod.library.renewhandler import LibRenewHandler
from mod.library.hothandler import HotHandler
from mod.pc.handler import PCHandler
from mod.jwc.handler import JWCHandler
from mod.schoolbus.handler import SchoolBusHandler
from mod.schoolbus.new_handler import NewSchoolBusHandler
from mod.phylab.handler import PhylabHandler
from mod.emptyroom.handler import CommonQueryHandler, QuickQueryHandler,NewHandler
from mod.emptyroom.new_new_handler import NewNewHandler
from mod.lecture.noticehandler import LectureNoticeHandler
from mod.user.handler import UserHandler
from mod.bedRoom.handler import RoomHandler
from mod.exam.handler import ExamHandler
from mod.yuyue.handler import YuyueHandler
from mod.log.handler import LogHandler
from tornado.options import define, options
import tornado.web
import tornado.ioloop
import tornado.options
# -*- coding: utf-8 -*-
# @Date    : 2014-06-25 15:43:36
# @Author  : xindervella@gamil.com yml_bright@163.com
# from mod.library.searchhandler import LibSearchHandler

define('port', default=7005, help='run on the given port', type=int)


class Application(tornado.web.Application):

    def __init__(self):
        handlers = [
            (r'/webserv2/auth', AuthHandler),
            (r'/webserv2/srtp', SRTPHandler),
            (r'/webserv2/term',TermHandler),
            (r'/webserv2/sidebar', SidebarHandler),
            (r'/webserv2/curriculum', CurriculumHandler),
            (r'/webserv2/gpa', GPAHandler),
            (r'/webserv2/pe', PEHandler),
            (r'/webserv2/pedetail', pedetailHandler),
            (r'/webserv2/simsimi', SIMSIMIHandler),
            (r'/webserv2/nic', NICHandler),
            (r'/webserv2/card', CARDHandler),
            (r'/webserv2/lecture', LectureHandler),
            (r'/webserv2/library_auth', LibAuthHandler),
            (r'/webserv2/library_auth_check', LibAuthCheckHandler),
            (r'/webserv2/library', LibListHandler),
            (r'/webserv2/library_hot',HotHandler),
            (r'/webserv2/renew', LibRenewHandler),
            # (r'/webserv2/search', LibSearchHandler),
            (r'/webserv2/phyLab',PhylabHandler),
            (r'/webserv2/pc', PCHandler),
            (r'/webserv2/jwc', JWCHandler),
            (r'/webserv2/schoolbus', SchoolBusHandler),

            (r'/webserv2/newbus', NewSchoolBusHandler),