|
|
@@ -0,0 +1,364 @@
|
|
|
+#!/usr/bin/env python
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+from Stats import Stats
|
|
|
+import configparser
|
|
|
+from Network import Network
|
|
|
+from Texts import ContentFile
|
|
|
+import datetime
|
|
|
+import math
|
|
|
+import json
|
|
|
+import random
|
|
|
+import lib.MoonPhase as mp
|
|
|
+import os
|
|
|
+import re
|
|
|
+
|
|
|
+class NummericPronounce:
|
|
|
+ Normal = 0
|
|
|
+ Year = 1
|
|
|
+ Time = 2
|
|
|
+
|
|
|
+class Text:
|
|
|
+
|
|
|
+
|
|
|
+ instance = None
|
|
|
+ content = dict()
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getInstance():
|
|
|
+ if Text.instance==None:
|
|
|
+ Text.instance = Text()
|
|
|
+ return Text.instance
|
|
|
+
|
|
|
+ def __init__(self):
|
|
|
+ self.stats = Stats.getInstance()
|
|
|
+ self.config = configparser.ConfigParser()
|
|
|
+ self.config.read("config.ini")
|
|
|
+ self.replacer = list()
|
|
|
+ # TODO: Replacer.js laden, und alle 60-180 Sekunden eine List-Variable mit möglichen Antworten füllen / aktualisieren
|
|
|
+ # z.B. aus der Replacer.js "badwords" mit allen möglichen Antworten, abhängig der Requirements, in die Variable "replacer["badwords"][]" füllen
|
|
|
+ # Weitere mögliche Wortlisten: "niceword" (incl cuteness, wenn verspieltheit hoch ist)
|
|
|
+ self.readReplacer()
|
|
|
+
|
|
|
+
|
|
|
+ def getText(self, intent, tags):
|
|
|
+ if intent not in self.content:
|
|
|
+ if os.path.isfile("text/"+intent+".json") == False:
|
|
|
+ print("Failed to load intent text: "+intent)
|
|
|
+ return ""
|
|
|
+ self.content[intent] = ContentFile.ContentFile(intent+".json")
|
|
|
+ return self.content[intent].getText(tags)
|
|
|
+
|
|
|
+ def executeText(self, intent, tags):
|
|
|
+ if intent not in self.content:
|
|
|
+ if os.path.isfile("text/"+intent+".json") == False:
|
|
|
+ print("Failed to load intent text: "+intent)
|
|
|
+ return ""
|
|
|
+ self.content[intent] = ContentFile.ContentFile(intent+".json")
|
|
|
+ return self.formatText(self.content[intent].executeText(tags))
|
|
|
+
|
|
|
+ def formatText(self, text:str ) -> str:
|
|
|
+ if text.find("{"):
|
|
|
+ if text.find("{device."):
|
|
|
+ text = text.replace("{device.name}",self.config["global"]["DeviceName"])
|
|
|
+ text = text.replace("{device.owner}",self.config["global"]["Owner"])
|
|
|
+ text = text.replace("{device.ip}", Network.getIp())
|
|
|
+ text = text.replace("{device.host}", Network.getHostName())
|
|
|
+ text = text.replace("{device.hostname}", Network.getHostName())
|
|
|
+ if text.find("{datetime."):
|
|
|
+ #Tomorow: datetime.datetime.now() + datetime.timedelta(days=1)
|
|
|
+ #Yesterday: datetime.datetime.now() - datetime.timedelta(days=1)
|
|
|
+ text = self._formatText_DateTime(text,datetime.datetime.now(),"now")
|
|
|
+ text = self._formatText_DateTime(text,datetime.datetime.now() + datetime.timedelta(days=1),"tomorow")
|
|
|
+ text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"yesterday")
|
|
|
+ text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"mordning") #TODO
|
|
|
+ text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"midday") #TODO
|
|
|
+ text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"evening") #TODO
|
|
|
+ text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"night") #TODO
|
|
|
+ if text.find("{weather."):
|
|
|
+ pass
|
|
|
+ if text.find("{house."):
|
|
|
+ pass
|
|
|
+ if text.find("{event."):
|
|
|
+ pass
|
|
|
+ if text.find("{calender."):
|
|
|
+ pass
|
|
|
+ if text.find("{"):
|
|
|
+ print("Enter Replacer Loop")
|
|
|
+ deadcounter=0
|
|
|
+ for k in self.replacer:
|
|
|
+ print("- Search for '"+k+"'")
|
|
|
+ notfound=False
|
|
|
+ while notfound==False:
|
|
|
+ if text.find("{"+k+"|") >= 0:
|
|
|
+ print("- found {"+k+"|")
|
|
|
+ word = self.getRandomWord(self.replacer[k])
|
|
|
+ if word=="":
|
|
|
+ text = re.sub("\\{"+k+"(?:\\|([a-z]{0,5}))?\\}","",text,1)
|
|
|
+ else:
|
|
|
+ text = re.sub("\\{"+k+"(?:\\|([a-z]{0,5}))?\\}",word+"\\1",text,1)
|
|
|
+
|
|
|
+ #pos1 = text.find("{"+k+"|")
|
|
|
+ #pos2 = pos1 + 2 + len(k)
|
|
|
+ #pos3 = text.find("}",pos1)
|
|
|
+
|
|
|
+ #res = text[0:pos1] + word + text[pos2:pos3-pos2] + text[pos3:]
|
|
|
+ #text=res
|
|
|
+
|
|
|
+ elif text.find("{"+k+"}") >= 0:
|
|
|
+ print("- found {"+k+"}")
|
|
|
+ text = re.sub("\\{"+k+"\\}",self.getRandomWord(self.replacer[k]),text,1)
|
|
|
+ else:
|
|
|
+ notfound=True
|
|
|
+ break
|
|
|
+ deadcounter+=1
|
|
|
+ if deadcounter > 40:
|
|
|
+ break
|
|
|
+ print("Eexit Replacer Loop")
|
|
|
+ return text
|
|
|
+
|
|
|
+ def _formatText_DateTime(self,text:str,dt:datetime.datetime,name:str):
|
|
|
+ name="{datetime."+name+"."
|
|
|
+ if text.find(name):
|
|
|
+ dt = datetime.datetime.now() + datetime.timedelta(days=1)
|
|
|
+ text = text.replace(name+"weekday}", self.getWeekDay(dt.weekday()) )
|
|
|
+ text = text.replace(name+"year}", self.getNumericPronounce(dt.year,0, NummericPronounce.Year) )
|
|
|
+ text = text.replace(name+"month}", self.getMonthName(dt.month) )
|
|
|
+ text = text.replace(name+"day}", self.getNumericDottedPronounce(dt.day) )
|
|
|
+ text = text.replace(name+"hour}", self.getNumericPronounce(dt.hour) )
|
|
|
+ text = text.replace(name+"minute}", self.getNumericPronounce(dt.minute) )
|
|
|
+ text = text.replace(name+"seconds}", self.getNumericPronounce(dt.second) )
|
|
|
+ text = text.replace(name+"second}", self.getNumericPronounce(dt.second) )
|
|
|
+ text = text.replace(name+"}", self.getDateString(dt) )
|
|
|
+ text = text.replace(name+"moonphase}", mp.phase(time=dt)["name"] )
|
|
|
+ return text
|
|
|
+
|
|
|
+ def getRandomWord(self, items:list) -> str:
|
|
|
+ if len(items) > 0:
|
|
|
+ return random.choice(items)
|
|
|
+ else:
|
|
|
+ return ""
|
|
|
+
|
|
|
+ def readReplacer(self):
|
|
|
+ tmp = {}
|
|
|
+ with open("text/Replacer.json") as json_file:
|
|
|
+ data = json.load(json_file)
|
|
|
+ for k in data:
|
|
|
+ tmp[k] = list()
|
|
|
+ add = True
|
|
|
+ for i in data[k]:
|
|
|
+ if "mood_required" in i:
|
|
|
+ statKeys = ["angry","annoyed","aroused","bored","compfortable","depressive","energy","excited","exhausted",
|
|
|
+ "freezy","funny","happyness","hot","humanity","hungry","intelligent","irritated","lonely","naiv",
|
|
|
+ "playful","sad","shy","sleepy","soziality","temperate","toLoud","toQuiet","usefull","useless"]
|
|
|
+ for sk in statKeys:
|
|
|
+ if sk+"_max" in i["mood_required"] and i["mood_required"][sk+"_max"] <= getattr(self.stats.deviceStats,sk):
|
|
|
+ add = False
|
|
|
+ break
|
|
|
+ if sk+"_min" in i["mood_required"] and i["mood_required"][sk+"_min"] >= getattr(self.stats.deviceStats,sk):
|
|
|
+ add = False
|
|
|
+ break
|
|
|
+ if add == True and "text" in i:
|
|
|
+ for t in i["text"]:
|
|
|
+ tmp[k].append(t)
|
|
|
+ self.replacer = tmp
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getWeekDay(weekday:int) -> str:
|
|
|
+ weekdays = [
|
|
|
+ "Sonntag",
|
|
|
+ "Montag",
|
|
|
+ "Dienstag",
|
|
|
+ "Mittwoch",
|
|
|
+ "Donnerstag",
|
|
|
+ "Freitag",
|
|
|
+ "Samstag",
|
|
|
+ "Sonntag"
|
|
|
+ ]
|
|
|
+ return weekdays[weekday]
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getMonthName(month:int) -> str:
|
|
|
+ monthnames = [
|
|
|
+ "",
|
|
|
+ "Januar",
|
|
|
+ "Februar",
|
|
|
+ "März",
|
|
|
+ "April",
|
|
|
+ "Mai",
|
|
|
+ "Juni",
|
|
|
+ "Juli",
|
|
|
+ "August",
|
|
|
+ "September",
|
|
|
+ "Oktober",
|
|
|
+ "November",
|
|
|
+ "Dezember"
|
|
|
+ ]
|
|
|
+ return monthnames[month]
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getNumericPronounce(num:float, decimals:int = 2, type:int = NummericPronounce.Normal) -> str:
|
|
|
+ ''' Formats a integer or floating point value into a readable string
|
|
|
+ num:float - The Number that should be writeable
|
|
|
+ decimals:int - the amount of decimals (max 6)
|
|
|
+
|
|
|
+ Range: -999,999,999.999999 to 999,999,999.999999
|
|
|
+
|
|
|
+ Returns :str'''
|
|
|
+
|
|
|
+
|
|
|
+ if type == NummericPronounce.Year:
|
|
|
+ s2=""
|
|
|
+ if num<0:
|
|
|
+ num*=-1
|
|
|
+ s2=" vor Christus"
|
|
|
+ if num>=1300 and num<2200:
|
|
|
+ num3 = math.floor(num/100)
|
|
|
+ s = Text.getNumericPronounce(num3)
|
|
|
+ num2 = num % 100
|
|
|
+ if(num2>9):
|
|
|
+ s += " " + Text.getNumericPronounce(num2)
|
|
|
+ else:
|
|
|
+ s += " null " + Text.getNumericPronounce(num2 % 10)
|
|
|
+ return s+s2
|
|
|
+ else:
|
|
|
+ # Check for negative numbers
|
|
|
+ if num<0:
|
|
|
+ return "Minus " + Text.getNumericPronounce(num * -1)
|
|
|
+
|
|
|
+ # Check for decimal
|
|
|
+ if math.floor(num)!=math.ceil(num):
|
|
|
+ if decimals<1:
|
|
|
+ num=math.floor(num)
|
|
|
+ else:
|
|
|
+ s = Text.getNumericPronounce(math.floor(num))
|
|
|
+ num -= math.floor(num)
|
|
|
+ s+=" Komma"
|
|
|
+ s+= " " + Text.getNumericPronounce(math.floor(num*10)%10)
|
|
|
+ if decimals>=2: s+= " " + Text.getNumericPronounce(math.floor(num*100)%10)
|
|
|
+ if decimals>=3: s+= " " + Text.getNumericPronounce(math.floor(num*1000)%10)
|
|
|
+ if decimals>=4: s+= " " + Text.getNumericPronounce(math.floor(num*10000)%10)
|
|
|
+ if decimals>=5: s+= " " + Text.getNumericPronounce(math.floor(num*100000)%10)
|
|
|
+ if decimals>=6: s+= " " + Text.getNumericPronounce(math.floor(num*1000000)%10)
|
|
|
+ return s
|
|
|
+
|
|
|
+ mod = num%10
|
|
|
+ zehner=(num-mod) % 100
|
|
|
+ hunderter=(num-mod-zehner) % 1000
|
|
|
+ tausender=(num-mod-zehner-hunderter) % 1000000
|
|
|
+ millonener=(num-mod-zehner-hunderter-tausender) % 1000000000
|
|
|
+ if num==0: return "null"
|
|
|
+ elif num==1: return "eins" # handels 1 only
|
|
|
+ elif num==2: return "zwei" # handels 2, 200, 302, 2.000, 2.000.000
|
|
|
+ elif num==3: return "drei"
|
|
|
+ elif num==4: return "vier"
|
|
|
+ elif num==5: return "fünf"
|
|
|
+ elif num==6: return "sechs"
|
|
|
+ elif num==7: return "sieben"
|
|
|
+ elif num==8: return "acht"
|
|
|
+ elif num==9: return "neun"
|
|
|
+ elif num==10: return "zehn"
|
|
|
+ elif num==11: return "elf"
|
|
|
+ elif num==12: return "zwölf"
|
|
|
+ elif num<=19: return Text.getNumericPronounce(mod)+"zehn"
|
|
|
+ elif num==20: return "zwanzig"
|
|
|
+ elif num==30: return "dreissig"
|
|
|
+ elif num==60: return "sechzig"
|
|
|
+ elif num==70: return "siebzig"
|
|
|
+ elif num<=99 and mod == 0: return Text.getNumericPronounce(zehner/10)+"zig"
|
|
|
+ elif num<=99 and mod == 1: return "einund"+Text.getNumericPronounce(zehner) # handels 21, 31, 41, 51, ...
|
|
|
+ elif num<=99 and mod > 1: return Text.getNumericPronounce(mod) + "und"+ Text.getNumericPronounce(zehner) #handels 22, 23, 24, 25, ... 32, 33, 34, ..., 42, 53, ....
|
|
|
+ elif num==100: return "einhundert" # handels 100
|
|
|
+ elif num<=199: return "einhundert" + Text.getNumericPronounce(num%100) # handels 101, 102, 103, ...
|
|
|
+ elif num<=999 and num%100==0: return Text.getNumericPronounce(hunderter/100)+"hundert" # handels 200, 300, 400, 500, 600, 700, 800, 900
|
|
|
+ elif num<=999: return Text.getNumericPronounce(hunderter/100)+"hundert"+Text.getNumericPronounce(num%100) # handels 201, 202, ... 301, 302
|
|
|
+ elif num==1000: return "eintausend"
|
|
|
+ elif num==10000: return "zehntausend"
|
|
|
+ elif num==100000: return "einhunderttausend"
|
|
|
+ elif num==1000000: return "eine millionen"
|
|
|
+ elif num<=1999: return "eintausend"+Text.getNumericPronounce(num%1000)
|
|
|
+ elif num<=999999 and num%1000==0: return Text.getNumericPronounce(tausender/1000)+"tausend" # handels 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000
|
|
|
+ elif num<=999999: return Text.getNumericPronounce(tausender/1000)+"tausend "+Text.getNumericPronounce(num%1000)
|
|
|
+ elif num<=1999999: return "eine millionen "+Text.getNumericPronounce(millonener%1000000)
|
|
|
+ elif num<=999999999 and num%1000000==0: return Text.getNumericPronounce(millonener/1000000)+" millionen" # handels 2mio, 3mio, 4mio, 5mio, 6mio, 7mio, 8mio, 9mio
|
|
|
+ elif num<=999999999: return Text.getNumericPronounce(millonener/1000000)+" millionen "+Text.getNumericPronounce(num%1000000)
|
|
|
+ else: print("ErrNum: "+num)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getNumericDottedPronounce(num:int) -> str:
|
|
|
+ if num==1:
|
|
|
+ return "erste"
|
|
|
+ elif num==3:
|
|
|
+ return "dritte"
|
|
|
+ elif num==8:
|
|
|
+ return "achte"
|
|
|
+ elif num>= 20:
|
|
|
+ return Text.getNumericPronounce(num)+"ste"
|
|
|
+ else:
|
|
|
+ return Text.getNumericPronounce(num)+"te"
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getDateString(date, WeekDay:bool = True, Year:bool = True) -> str:
|
|
|
+ if WeekDay and Year:
|
|
|
+ return Text.getWeekDay(date.weekday())+", der "+Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)+" "+Text.getNumericPronounce(date.year, 0, NummericPronounce.Year)
|
|
|
+ pass
|
|
|
+ elif WeekDay:
|
|
|
+ return Text.getWeekDay(date.weekday())+", der "+Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)
|
|
|
+ elif Year:
|
|
|
+ return Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)+" "+Text.getNumericPronounce(date.year, 0, NummericPronounce.Year)
|
|
|
+ else:
|
|
|
+ return Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def getTimeString(time, Seconds:bool=False, Use24:bool=False) -> str:
|
|
|
+ if Seconds:
|
|
|
+ return Text.getTimeString(time,False,Use24)+" und " + time.seconds+" Sekunden"
|
|
|
+ else:
|
|
|
+ min = time.minute
|
|
|
+ sur=""
|
|
|
+ surn=""
|
|
|
+ if Use24:
|
|
|
+ hour=Text.getNumericPronounce(time.hour)
|
|
|
+ hourn=Text.getNumericPronounce((time.hour+1)%24)
|
|
|
+ else:
|
|
|
+ hour=Text.getNumericPronounce(time.hour%12)
|
|
|
+ hourn=Text.getNumericPronounce((time.hour+1)%12)
|
|
|
+ if time.hour<5 or time.hour>21: sur=" Nachts"
|
|
|
+ elif time.hour<11: sur=" Morgens"
|
|
|
+ elif time.hour<16: sur=" Mittags"
|
|
|
+ elif time.hour<19: sur=" Nachmittags"
|
|
|
+ else: sur=" Abends"
|
|
|
+
|
|
|
+ if time.hour<4 or time.hour>20: surn=" Nachts"
|
|
|
+ elif time.hour<10: surn=" Morgens"
|
|
|
+ elif time.hour<15: surn=" Mittags"
|
|
|
+ elif time.hour<18: surn=" Nachmittags"
|
|
|
+ else: surn=" Abends"
|
|
|
+
|
|
|
+ if time.hour==23:
|
|
|
+ shour=hour
|
|
|
+ shourn="Mitternacht"
|
|
|
+ elif time==0:
|
|
|
+ shour="Mitternacht"
|
|
|
+ shourn=hourn
|
|
|
+ else:
|
|
|
+ shour=hour
|
|
|
+ shourn=hourn
|
|
|
+
|
|
|
+ if min==0:
|
|
|
+ return "punkt "+shour+sur
|
|
|
+ elif min==30:
|
|
|
+ return "halb "+shourn+surn
|
|
|
+ elif min>=27 and min<30:
|
|
|
+ return "kurz vor halb "+shourn+surn
|
|
|
+ elif min>30 and min<=33:
|
|
|
+ return "kurz nach halb "+shourn+surn
|
|
|
+ elif min==15:
|
|
|
+ return "viertel nach "+shour+sur
|
|
|
+ elif min==45:
|
|
|
+ return "viertel vor "+shourn+surn
|
|
|
+ elif min<=3:
|
|
|
+ return "kurz nach "+shour+sur
|
|
|
+ elif min>=37:
|
|
|
+ return "kurz vor "+shourn+surn
|
|
|
+ else:
|
|
|
+ return hour+" Uhr "+Text.getNumericPronounce(min)+sur
|