X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fpystan%2Flib%2Fstan.py;fp=src%2Fpystan%2Flib%2Fstan.py;h=337672df196009d0b3fc315ae83c8728a02ea6a4;hb=a0f2cf4120a390bd527b3787775ad564fd04d2e6;hp=0000000000000000000000000000000000000000;hpb=ff6d19caa498ee5aa72d76fc594847886eaf567e;p=pystan diff --git a/src/pystan/lib/stan.py b/src/pystan/lib/stan.py new file mode 100644 index 0000000..337672d --- /dev/null +++ b/src/pystan/lib/stan.py @@ -0,0 +1,478 @@ +# -*- coding: UTF-8 -*- + +import os, sys, time, re +import urllib, urllib2, urlparse, cgi +from urllib2 import URLError + + +from timetable_parser import StanTimetableParser + +class STAN: + + RSS_URL = 'http://www.reseau-stan.com/rss' + + get_params = [ 'rub_code', 'gpl_id', 'thm_id', 'lineid', 'date', 'hour', 'direction' ] + + def lines(self): + + return [ + { 'id': 144, + 'name': u"Nancy République / Bouxières-aux-Dames", + 'numbers': ["322"], + 'fg-color': '#fff', + 'bg-color': '#6ecbf1' + }, + { 'id': 145, + 'name': u"Vandoeuvre Vᅢᄅlodrome / Chaligny", + 'numbers': ["511"], + 'fg-color': '#fff', + 'bg-color': '#a3b909' + }, + { 'id': 146, + 'name': u"Nancy République / Frouard Le Nid", + 'numbers': ["323"], + 'fg-color': '#fff', + 'bg-color': '#f5a3c8' + }, + { 'id': 147, + 'name': u"Vandoeuvre Vélodrome / Pont Saint-Vincent", + 'numbers': ["512"], + 'fg-color': '#fff', + 'bg-color': '#c00266' + }, + { 'id': 148, + 'name': u"Nancy République / Pompey Les Vannes", + 'numbers': ["324"], + 'fg-color': '#fff', + 'bg-color': '#d80b8c' + }, + { 'id': 149, + 'name': u"Vandoeuvre Vélodrome / Messein", + 'numbers': ["514"], + 'fg-color': '#fff', + 'bg-color': '#006d2c' + }, + { 'id': 150, + 'name': u"Nancy République / Pompey Fonds de Lavaux", + 'numbers': ["325"], + 'fg-color': '#fff', + 'bg-color': '#b4d8be' + }, + { 'id': 151, + 'name': u"Nancy Place Carnot / Chaligny", + 'numbers': ["521"], + 'fg-color': '#a3b909', + 'bg-color': '#fff' + }, + { 'id': 152, + 'name': u"Nancy République / Saint-Nicolas Le Nid", + 'numbers': ["621"], + 'fg-color': '#fff', + 'bg-color': '#0b0a4b' + }, + { 'id': 153, + 'name': u"Nancy Place Carnot / Pont Saint-Vincent", + 'numbers': ["522"], + 'fg-color': '#c00266', + 'bg-color': '#fff' + }, + { 'id': 154, + 'name': u"Nancy République / Dombasle Maroc", + 'numbers': ["624"], + 'fg-color': '#fff', + 'bg-color': '#fb1518' + }, + { 'id': 155, + 'name': u"Nancy Place Carnot / Bainville-sur-Madon", + 'numbers': ["523"], + 'fg-color': '#81d0e3', + 'bg-color': '#fff' + }, + { 'id': 157, + 'name': u"Nancy République / Saint-Nicolas République", + 'numbers': ["622"], + 'fg-color': '#fff', + 'bg-color': '#0d97a8' + }, + { 'id': 156, + 'name': u"Nancy République / Dombasle Stand", + 'numbers': ["623"], + 'fg-color': '#fff', + 'bg-color': '#fe6612' + }, + { 'id': 158, + 'name': u"Nancy République / Champigneulles", + 'numbers': ["321"], + 'fg-color': '#fff', + 'bg-color': '#d3b6d1' + }, + { 'id': 126, + 'name': u"Vandoeuvre Parc des Expositions / Nancy République", + 'numbers': ["129"], + 'fg-color': '#fff', + 'bg-color': '#92bbad' + }, + { 'id': 133, + 'name': u"Ligne 80", + 'numbers': ["80"], + 'bg-color': 'yellow' + }, + { 'id': 138, + 'name': u"Vandoeuvre CHU Brabois / Essey Mouzimpré", + 'numbers': ["Tram 1"], + 'fg-color': '#fff', + 'bg-color': '#ff0000' + }, + { 'id': 141, + 'name': u"Vandoeuvre CHU Brabois / Centre d\'accueil - Villers les Essarts", + 'numbers': ["Ptit Stan Vilers"], + 'bg-color': 'yellow' + }, + { 'id': 143, + 'name': u"Vandoeuvre CHU Brabois / Vandoeuvre Nations - Médecine préventive ", + 'numbers': ["Ptit Stan Vandoeuvre"], + 'bg-color': 'yellow' + }, + { 'id': 140, + 'name': u"Laxou Sapinière / Laxou Provinces", + 'numbers': ["Ptit Stan Laxou"], + 'bg-color': 'yellow' + }, + { 'id': 142, + 'name': u"Nancy Carnot", + 'numbers': ["Ptit Stan Colline"], + 'bg-color': 'yellow' + }, + { 'id': 134, + 'name': u"Malzéville Sadi Carnot - Nancy Cimetière du Sud", + 'numbers': ["Minibus"], + 'bg-color': 'yellow' + }, + { 'id': 159, + 'name': u"StanU", + 'numbers': ["110"], + 'bg-color': 'yellow' + }, + { 'id': 112, + 'name': u"Maxéville Champ le Boeuf - Nancy Haut du Lièvre / Jarville Sion", + 'numbers': ["111", "112"], + 'fg-color': '#fff', + 'bg-color': '#71228d' + }, + { 'id': 96, + 'name': u"Houdemont / Vandoeuvre Charmois", + 'numbers': ["114"], + 'fg-color': '#000', + 'bg-color': '#b6a6d3' + }, + { 'id': 98, + 'name': u"Ludres / Villers Lycée Stanislas", + 'numbers': ["115"], + 'fg-color': '#fff', + 'bg-color': '#705aac' + }, + { 'id': 101, + 'name': u"Fléville Fleurychamp - Heillecourt / Villers Lycée Stanislas", + 'numbers': ["116"], + 'fg-color': '#fff', + 'bg-color': '#755eac' + }, + { 'id': 103, + 'name': u"Nancy Beauregard / Nancy République", + 'numbers': ["121"], + 'fg-color': '#fff', + 'bg-color': '#339d2f' + }, + { 'id': 135, + 'name': u"Villers Clairlieu / Nancy République", + 'numbers': ["122", "126"], + 'fg-color': '#000', + 'bg-color': '#9cca1f' + }, + { 'id': 106, + 'name': u"Vandoeuvre Nations / Nancy République", + 'numbers': ["123"], + 'fg-color': '#000', + 'bg-color': '#a9d72f' + }, + { 'id': 109, + 'name': u"Laxou Mouzon / Nancy République", + 'numbers': ["124"], + 'fg-color': '#fff', + 'bg-color': '#39a63b' + }, + + { 'id': 118, + 'name': u"Laxou Provinces / Seichamps", + 'numbers': ["130"], + 'fg-color': '#fff', + 'bg-color': '#048a96' + }, + { 'id': 95, + 'name': u"Maxéville Mairie / Jarville Sion - Heillecourt - Fléville De la Noue", + 'numbers': ["131", "132", "133"], + 'fg-color': '#000', + 'bg-color': '#82cee6' + }, + { 'id': 97, + 'name': u"Villers Lycée Stanislas / Maxéville Lafayette - Malzéville Savlons", + 'numbers': ["134", "135"], + 'fg-color': '#fff', + 'bg-color': '#1693cb' + }, + { 'id': 100, + 'name': u"Nancy Cours Léopold / Laneuveville - La Madeleine", + 'numbers': ["136", "137"], + 'fg-color': '#fff', + 'bg-color': '#6f88c1' + }, + { 'id': 102, + 'name': u"Laxou Champ le Boeuf / Vandoeurvre Roberval", + 'numbers': ["138"], + 'fg-color': '#fff', + 'bg-color': '#123e97' + }, + { 'id': 104, + 'name': u"Nancy Cours Léopold / Ludres", + 'numbers': ["139"], + 'fg-color': '#fff', + 'bg-color': '#6f87c7' + }, + { 'id': 114, + 'name': u"Malzéville / Saulxures Forêt - Art sur Meurthe", + 'numbers': ["141", "142"], + 'fg-color': '#fff', + 'bg-color': '#ff750e' + }, + { 'id': 108, + 'name': u"Malzéville Pixérécourt / Saulxures", + 'numbers': ["161"], + 'fg-color': '#000', + 'bg-color': '#ffff33' + }, + { 'id': 116, + 'name': u"Essey C.E.S / Gérard Barrois Stade Marcel Picot", + 'numbers': ["162"], + 'fg-color': '#000', + 'bg-color': '#f59638' + }, + { 'id': 107, + 'name': u"Dommartemont / Jarville Sion", + 'numbers': ["163"], + 'fg-color': '#000', + 'bg-color': '#fad956' + }, + { 'id': 110, + 'name': u"Essey Mouzimpré / Seichamps - Pulnoy (Lignes accessibles PMR)", + 'numbers': ["171", "172"], + 'bg-color': '#f38ab3' + } + ] + + def schedules_cache_dirname(self): + pystan_schedules = os.path.expanduser('~/.pystan/cache/schedules') + if not os.path.isdir(pystan_schedules): + #os.makedirs('~/.pystan/cache/schedules') + pass + return pystan_schedules + + def filter_params(self, params): + only_wanted = {} + for key in params: + if key in self.get_params: + only_wanted[key] = params[key] + return only_wanted + + def schedule_cache_filename(self, params): + params['date'] = self.schedules_cache_dateformat(params['date']) + params = [ str(key)+"="+str(params[key]) for key in iter(params)] + params.sort() + filename = '_'.join(params) + filename = filename.replace('/', '-') + return "%s/%s" % (self.schedules_cache_dirname(), filename) + + def schedules_cache_dateformat(self, date): + date = time.strptime(date, "%d/%m/%Y") + day_n = int(time.strftime("%w", date)) + # saturday / sunday + if day_n == 0 or day_n == 6: + date = time.strftime("%a/%m/%Y", date) + # week + else: + date = time.strftime("week/%m/%Y", date) + return date + + + def default_timetable_params(self, params): + for param, default in { 'rub_code':6, 'thm_id':6, 'gpl_id':0 }.items(): #{'sens':1, 'date':'01/01/01', 'hour':'12', 'index':'1'}: + if not params.has_key(param) or params[param] is None: + params[param] = default + return params + + def search(self, from_location, from_city, to_location, to_city, datetime, restrict=68): + cached_result = self.cached_search(from_location, from_city, to_location, to_city, datetime, restrict) + if cached_search is not None: + return cached_result + + ''' + POST to http://www.reseau-stan.com/ri/index.asp + from_location: keywordsDep + from_city: comDep + to_location: keywordsArr + to_city: comArr + date: laDate (11/03/2009) + hour: lHeure (13 = 13h) + minute: laMinute + restrict: typeDate (68 = partir apres, 65 = arriver avant) + ''' + pass + + def cached_search(self, from_location, from_city, to_location, to_city, datetime, restrict=68): + cache_id = '-'.join([ from_location, from_city, to_location, to_city, datetime, restrict ]) + pass + + def load_timetable(self, lineid, params=None, bypass=False): + params = self.default_timetable_params(params) + params['lineid'] = lineid + params = self.filter_params(params) + + timetable_raw_html_file = None + + if timetable_raw_html_file is None: + timetable_raw_html_file = self.load_timetable_local(params, bypass) + + if timetable_raw_html_file is None: + timetable_raw_html_file = self.load_timetable_remote(params) + + if timetable_raw_html_file is None: + print "WARNING:\tNo cache file and no internet connection" + + if timetable_raw_html_file: + parser = StanTimetableParser() + parser.feed(timetable_raw_html_file) + parser.close() + parsed = parser.result + + if parsed['navigation'].has_key('next'): + index_next = urlparse.urlsplit(parsed['navigation']['next'])[3] + index_next = cgi.parse_qs(index_next) + parsed['navigation']['next'] = index_next['index'][0] + + if parsed['navigation'].has_key('prev'): + index_prev = urlparse.urlsplit(parsed['navigation']['prev'])[3] + index_prev = cgi.parse_qs(index_prev) + parsed['navigation']['prev'] = index_prev['index'][0] + + if len(parsed['stations']) > 0: + parsed['stations'] = self.extract_stations_infos(parsed['stations']) + pass + + return parsed + + else: + return timetable_raw_html_file + + def load_timetable_remote(self, params): + url = 'http://www.reseau-stan.com/horaires_ligne/index.asp' + + get_params = params.copy() + get_params['lign_id'] = get_params['lineid']; del(get_params['lineid']) + + if get_params.has_key('direction') and int(get_params['direction']) > 0: + get_params['sens'] = 2 + del(get_params['direction']) + else: + get_params['sens'] = 1 + + if get_params.has_key('hour'): + get_params['index'] = get_params['hour'] + del(get_params['hour']) + + req = urllib2.Request(url, urllib.urlencode(get_params)) + + print "GET FROM:\t%s?%s" % (url, urllib.urlencode(get_params)) + + file_data = None + + try: + response = urllib2.urlopen(req) + file_data = response.read() + except URLError, e: + print "WARNING:\t%s" % e + + if file_data is not None: + self.save_timetable_local(file_data, params) + return file_data + + def load_timetable_local(self, params, bypass=False): + file = self.schedule_cache_filename(params) + file_data = None + max_age = 999L + + print "GET FROM:\t%s" % file + + if not os.path.isfile(file): + #print "WARNING: %s does not exists" % file + file_data = None + + elif bypass or os.stat(file).st_mtime <= int(time.time()) + max_age: + response = open(file) + try: + file_data = response.read() + finally: + response.close() + else: + print "WARNING:\t%s exists but is too old" % file + file_data = False + + return file_data + + def save_timetable_local(self, file_data, params): + + file_data = re.compile('(
.*)