From 0e757e1d3822a0adeeb086fbf3e56c20cb1bdb40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20P=C3=A9rez-Cerezo?= Date: Tue, 28 Aug 2018 17:27:55 +0200 Subject: Added option for position, radius and distances, more plugins --- bin/mensa | 28 +++++++++++++++++++++++++--- mensa/backends/mathemensa.py | 2 +- mensa/backends/satyam.py | 2 +- mensa/backends/singh.py | 2 +- mensa/backends/studentenwerk.py | 23 +++++++++++++++++++---- mensa/base.py | 18 +++++++++++++++++- mensa/frontends/html.py | 6 +++++- mensa/frontends/plain-text.py | 3 +++ mensa/logic.py | 22 +++++++++++++--------- 9 files changed, 85 insertions(+), 21 deletions(-) diff --git a/bin/mensa b/bin/mensa index 6e603cd..48ecac8 100755 --- a/bin/mensa +++ b/bin/mensa @@ -11,11 +11,14 @@ parser.add_argument('rest', nargs="*", parser.add_argument('-l', '--list-restaurants', dest='list', action='store_true', help='get list of restaurants') parser.add_argument('-f', '--formatter', dest='form', action='store', nargs=1, help="formatter to use") +parser.add_argument('-p', '--pos', dest='pos', action='store', nargs=1, help="Your current position") +parser.add_argument('-d', '--dist', dest='dist', action='store_true', help="Show distances to restaurants") +parser.add_argument('-r', '--radius', dest='rad', action='store', nargs=1, help="Radius to find restaurants in") parser.add_argument('-g', '--vegetarian', dest='vegetarian', action='store_true', help='show only vegetarian meals') parser.add_argument('-G', '--vegan', dest='vegan', action='store_true', help='show only vegan meals') -parser.add_argument('-s', '--student-prices', dest='student', action='store_true', default=False, +parser.add_argument('--studentenwerk-prices', dest='student', action='store_true', default=False, help='show only student prices') parser.add_argument('--no-parallel', dest="no_parallel", action="store_true", default=False, help="Do not parallelize fetching, might help with rate-limited websites") @@ -28,10 +31,29 @@ logic.init_foodsources() logic.init_renderers() veggie = 0 form = ["plain-text"] +if args.dist and not args.pos or args.rad and not args.pos : + print("-d and -r require a position") + exit(1) + + +if args.pos : + try : + args.pos = tuple([ float(i) for i in args.pos[0].split(",")]) + assert len(args.pos) == 2 + except : + print("-p has the format LAT,LONG. For instance: 52.5133727,13.3240049") + exit(1) +if args.rad : + try : + args.rad = float(args.rad[0]) + except : + print("-r requires a floating point number!") + exit(1) if args.form : form = args.form + if args.vegetarian : veggie = 1 if args.vegan : @@ -47,5 +69,5 @@ restlist = None if args.rest : restlist = args.rest -foodl = logic.get_food(restlist, no_parallel=args.no_parallel) -logic.render(foodl, form, only_veggie=veggie, only_student_prices=args.student) +foodl = logic.get_food(restlist, no_parallel=args.no_parallel, pos=args.pos, rad=args.rad) +logic.render(foodl, form, only_veggie=veggie, only_student_prices=args.student, pos=args.pos, dist=args.dist) diff --git a/mensa/backends/mathemensa.py b/mensa/backends/mathemensa.py index 8f66805..559956d 100644 --- a/mensa/backends/mathemensa.py +++ b/mensa/backends/mathemensa.py @@ -13,7 +13,7 @@ from yapsy.IPlugin import IPlugin class Mathemensa(IPlugin) : def register_restaurants(self) : - r = Restaurant("Mathemensa", "Mathemensa", self, "dummy") + r = Restaurant("Mathekantine", "Mathekantine", self, "dummy", pos=(52.51388,13.3235066)) register_restaurant(r) def get_food_items(self, **kwargs) : diff --git a/mensa/backends/satyam.py b/mensa/backends/satyam.py index e08aed6..bf18dc5 100644 --- a/mensa/backends/satyam.py +++ b/mensa/backends/satyam.py @@ -9,7 +9,7 @@ from yapsy.IPlugin import IPlugin class Satyam(IPlugin): def register_restaurants(self) : - r = Restaurant("Satyam", "Satyam", self, "dummy") + r = Restaurant("Satyam", "Satyam", self, "dummy", pos=(52.5089202,13.3198446)) register_restaurant(r) def get_food_items(self, **kwargs) : s = sys.stderr diff --git a/mensa/backends/singh.py b/mensa/backends/singh.py index 844cc9c..393b5da 100644 --- a/mensa/backends/singh.py +++ b/mensa/backends/singh.py @@ -10,7 +10,7 @@ from yapsy.IPlugin import IPlugin class Signh(IPlugin) : def register_restaurants(self) : - r = Restaurant("Singh", "Mathe-Café", self, "dummy") + r = Restaurant("Singh", "Mathe-Café", self, "dummy", pos=(52.5133727,13.3240049)) register_restaurant(r) def get_food_items(self, **kwargs) : s = sys.stderr diff --git a/mensa/backends/studentenwerk.py b/mensa/backends/studentenwerk.py index f916096..89c45eb 100644 --- a/mensa/backends/studentenwerk.py +++ b/mensa/backends/studentenwerk.py @@ -10,7 +10,23 @@ from yapsy.IPlugin import IPlugin import multiprocessing import datetime + from yapsy import NormalizePluginNameForModuleName as normalize +mensenliste = {"TU Hardenbergstraße" : ["mensa-tu-hardenbergstra%C3%9Fe", (52.5097684, 13.3259478)], + "TU Marchstraße": ["cafeteria-tu-marchstra%C3%9Fe", ( 52.5166071, 13.3234066)], + "TU Skyline": ["cafeteria-tu-skyline", (52.5128648, 13.3200313)], + "TU Architektur": ["cafeteria-tu-architektur", (52.5137508, 13.3234541)], + "TU Ackerstraße": ["cafeteria-tu-ackerstra%C3%9Fe", (52.5386545, 13.3845294)], + "HU Nord": ["mensa-hu-nord", (52.52816,13.38208)], + "HU Oase Adlershof" : ["mensa-hu-oase-adlershof", ( 52.4293965, 13.5300404)], + "HU Süd": ["mensa-hu-sued", (52.5185929, 13.3928965)], + "HU Spandauer Straße": ["mensa-hu-spandauer-stra%C3%9Fe", (52.52096,13.40258)], + "HU „Jacob und Wilhelm Grimm Zentrum“": ["cafeteria-hu-im-jacob-und-wilhelm-grimm-zentrum", (52.52033,13.39083)], + "FU Herrenhaus Düppel": ["mensa-fu-herrenhaus-d%C3%BCppel", (52.4299794,13.2352233)], + "Mensa FU II Otto-von-Simson-Straße": ["mensa-fu-ii", (52.4531000, 13.2890712)], +} + + class Studentenwerk(IPlugin) : def fetch_page(self, mensa) : @@ -24,9 +40,8 @@ class Studentenwerk(IPlugin) : document = html5lib.parse(the_page, treebuilder="lxml") return document def register_restaurants (self) : - mensenliste = {"TU Hardenbergstraße" : "mensa-tu-hardenbergstra%C3%9Fe", "TU Marchstraße": "cafeteria-tu-marchstra%C3%9Fe", "TU Skyline": "cafeteria-tu-skyline", "TU Architektur": "cafeteria-tu-architektur", "TU Ackerstraße": "cafeteria-tu-ackerstra%C3%9Fe"} for h,n in mensenliste.items() : - r = Restaurant(normalize(h), h, self, "dummy", [n]) + r = Restaurant(normalize(h), h, self, "dummy", [n[0]], pos=n[1]) register_restaurant(r) def get_food_items(self, mensa="mensa-tu-hardenbergstra%C3%9Fe", ignore_nudelauswahl=False) : document = self.fetch_page(mensa) @@ -34,10 +49,10 @@ class Studentenwerk(IPlugin) : groups = [e for e in groupsel(document)] fl = [] for i in groups : - try: + try: name = CSSSelector('.splGroup')(i)[0].text except: - raise NoMenuError from None + raise NoMenuError from None sel = CSSSelector('.splMeal') meals = [e for e in sel(i)] for m in meals : diff --git a/mensa/base.py b/mensa/base.py index a6e8cfa..8db5b8c 100644 --- a/mensa/base.py +++ b/mensa/base.py @@ -36,17 +36,33 @@ def formt (food) : if i.desc : r = r+"\t "+i.desc+"\n" return r +from math import acos, radians, pi, cos, sin +def dist(pos1, pos2) : + # gives a rough estimate of the distance Accuracy: +/- cos(angle + # between coordinates)*37/2pi. (about +/- 50 m for distances). + # Distance is returned in km + if pos1 is None or pos2 is None : + return float("Inf") + lat1, long1 = pos1 + lat2, long2 = pos2 + + a = radians(90 - lat1); + b = radians(90 - lat2); + C = radians(abs(long1-long2)); + return acos(cos(a)*cos(b)+sin(a)*sin(b)*cos(C))*40040/(2*pi); + foodsources = {} renderers = {} class Restaurant(object): - def __init__(self, name, human_name, module, optional_args=[], obligatory_args=()): + def __init__(self, name, human_name, module, optional_args=[], obligatory_args=(), pos=None): self.name = name self.human_name = human_name self.module = module self.optional_args = optional_args self.obligatory_args = obligatory_args + self.pos = pos def get_food(self,**opt_args) : return self.module.get_food_items(*self.obligatory_args, **opt_args) diff --git a/mensa/frontends/html.py b/mensa/frontends/html.py index 8a5618f..c23d27c 100644 --- a/mensa/frontends/html.py +++ b/mensa/frontends/html.py @@ -12,6 +12,10 @@ class HTMLRenderer(IPlugin) : if not food : continue r = r+"

"+esc(restaurant.human_name)+"

"+"\n"#+base.formt(food) + if "pos" in options and restaurant.pos and "dist" in options : + ## display distance to restaurant + r=r+"
Distance: %.2f km
\n" % base.dist(options["pos"], restaurant.pos) + food.sort(key=lambda foo: foo.category) for i in food: if options["only_student_prices"] : @@ -29,7 +33,7 @@ class HTMLRenderer(IPlugin) : r=r+"
  • " + esc(i.name) + ""+ esc(price) + ""+ esc(vegkeys[i.veggie])+"\n" if i.desc : r = r+"
    "+esc(i.desc)+"
    \n" - r = r+"
  • " + r = r+"" r = r print(r) diff --git a/mensa/frontends/plain-text.py b/mensa/frontends/plain-text.py index 9147133..36b2a34 100644 --- a/mensa/frontends/plain-text.py +++ b/mensa/frontends/plain-text.py @@ -10,6 +10,9 @@ class TextRenderer(IPlugin) : if not food : continue r = r+"*"*20+restaurant.human_name+"*"*20+"\n"#+base.formt(food) + if "pos" in options and restaurant.pos and "dist" in options : + ## display distance to restaurant + r=r+"Distance: %.2f km\n" % base.dist(options["pos"], restaurant.pos) food.sort(key=lambda foo: foo.category) for i in food: if options["only_student_prices"] : diff --git a/mensa/logic.py b/mensa/logic.py index cae2421..1ae6a96 100755 --- a/mensa/logic.py +++ b/mensa/logic.py @@ -4,13 +4,14 @@ from mensa import base import urllib.error import os import sys +from math import acos, radians, pi, cos, sin from yapsy.PluginManager import PluginManager try: import multiprocessing parallel=True except: parallel = False - + def init_foodsources(): backends = PluginManager() backends.setPluginPlaces([os.path.join(os.path.dirname(os.path.realpath(__file__)),"backends")]) @@ -30,19 +31,22 @@ def init_renderers(): def get_food(restlist=False, no_parallel=False,**options) : foodl = [] + sources = [] + for k,i in base.foodsources.items() : + if restlist and not i.name in restlist : + continue + if options["pos"] and options["rad"] and base.dist(options["pos"], i.pos) > float(options["rad"]) : + continue + sources.append((k,i)) + if parallel and not no_parallel: r = [] - for k,i in base.foodsources.items() : - if restlist and not i.name in restlist : - continue - r.append(i) - + for k,i in sources : + r.append(i) foodl = get_food_parallel(r, ignore_nudelauswahl=True) else : - for k,i in base.foodsources.items() : - if restlist and not i.name in restlist : - continue + for k,i in sources : try : food = i.get_food(ignore_nudelauswahl=True) foodl.append((i, food)) -- cgit v1.2.3