main.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from Stats import Stats
  4. import configparser
  5. from Network import Network
  6. from Texts import ContentFile
  7. import datetime
  8. import math
  9. import json
  10. import random
  11. import lib.MoonPhase as mp
  12. import os
  13. import re
  14. class NummericPronounce:
  15. Normal = 0
  16. Year = 1
  17. Time = 2
  18. class Text:
  19. instance = None
  20. content = dict()
  21. @staticmethod
  22. def getInstance():
  23. if Text.instance==None:
  24. Text.instance = Text()
  25. return Text.instance
  26. def __init__(self):
  27. self.stats = Stats.getInstance()
  28. self.config = configparser.ConfigParser()
  29. self.config.read("config.ini")
  30. self.replacer = list()
  31. # TODO: Replacer.js laden, und alle 60-180 Sekunden eine List-Variable mit möglichen Antworten füllen / aktualisieren
  32. # z.B. aus der Replacer.js "badwords" mit allen möglichen Antworten, abhängig der Requirements, in die Variable "replacer["badwords"][]" füllen
  33. # Weitere mögliche Wortlisten: "niceword" (incl cuteness, wenn verspieltheit hoch ist)
  34. self.readReplacer()
  35. def getText(self, intent, tags):
  36. if intent not in self.content:
  37. if os.path.isfile("text/"+intent+".json") == False:
  38. print("Failed to load intent text: "+intent)
  39. return ""
  40. self.content[intent] = ContentFile.ContentFile(intent+".json")
  41. return self.content[intent].getText(tags)
  42. def executeText(self, intent, tags):
  43. if intent not in self.content:
  44. if os.path.isfile("text/"+intent+".json") == False:
  45. print("Failed to load intent text: "+intent)
  46. return ""
  47. self.content[intent] = ContentFile.ContentFile(intent+".json")
  48. return self.formatText(self.content[intent].executeText(tags))
  49. def formatText(self, text:str ) -> str:
  50. if text.find("{"):
  51. if text.find("{device."):
  52. text = text.replace("{device.name}",self.config["global"]["DeviceName"])
  53. text = text.replace("{device.owner}",self.config["global"]["Owner"])
  54. text = text.replace("{device.ip}", Network.getIp())
  55. text = text.replace("{device.host}", Network.getHostName())
  56. text = text.replace("{device.hostname}", Network.getHostName())
  57. if text.find("{datetime."):
  58. #Tomorow: datetime.datetime.now() + datetime.timedelta(days=1)
  59. #Yesterday: datetime.datetime.now() - datetime.timedelta(days=1)
  60. text = self._formatText_DateTime(text,datetime.datetime.now(),"now")
  61. text = self._formatText_DateTime(text,datetime.datetime.now() + datetime.timedelta(days=1),"tomorow")
  62. text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"yesterday")
  63. text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"mordning") #TODO
  64. text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"midday") #TODO
  65. text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"evening") #TODO
  66. text = self._formatText_DateTime(text,datetime.datetime.now() - datetime.timedelta(days=1),"night") #TODO
  67. if text.find("{weather."):
  68. pass
  69. if text.find("{house."):
  70. pass
  71. if text.find("{event."):
  72. pass
  73. if text.find("{calender."):
  74. pass
  75. if text.find("{"):
  76. print("Enter Replacer Loop")
  77. deadcounter=0
  78. for k in self.replacer:
  79. print("- Search for '"+k+"'")
  80. notfound=False
  81. while notfound==False:
  82. if text.find("{"+k+"|") >= 0:
  83. print("- found {"+k+"|")
  84. word = self.getRandomWord(self.replacer[k])
  85. if word=="":
  86. text = re.sub("\\{"+k+"(?:\\|([a-z]{0,5}))?\\}","",text,1)
  87. else:
  88. text = re.sub("\\{"+k+"(?:\\|([a-z]{0,5}))?\\}",word+"\\1",text,1)
  89. #pos1 = text.find("{"+k+"|")
  90. #pos2 = pos1 + 2 + len(k)
  91. #pos3 = text.find("}",pos1)
  92. #res = text[0:pos1] + word + text[pos2:pos3-pos2] + text[pos3:]
  93. #text=res
  94. elif text.find("{"+k+"}") >= 0:
  95. print("- found {"+k+"}")
  96. text = re.sub("\\{"+k+"\\}",self.getRandomWord(self.replacer[k]),text,1)
  97. else:
  98. notfound=True
  99. break
  100. deadcounter+=1
  101. if deadcounter > 40:
  102. break
  103. print("Eexit Replacer Loop")
  104. return text
  105. def _formatText_DateTime(self,text:str,dt:datetime.datetime,name:str):
  106. name="{datetime."+name+"."
  107. if text.find(name):
  108. dt = datetime.datetime.now() + datetime.timedelta(days=1)
  109. text = text.replace(name+"weekday}", self.getWeekDay(dt.weekday()) )
  110. text = text.replace(name+"year}", self.getNumericPronounce(dt.year,0, NummericPronounce.Year) )
  111. text = text.replace(name+"month}", self.getMonthName(dt.month) )
  112. text = text.replace(name+"day}", self.getNumericDottedPronounce(dt.day) )
  113. text = text.replace(name+"hour}", self.getNumericPronounce(dt.hour) )
  114. text = text.replace(name+"minute}", self.getNumericPronounce(dt.minute) )
  115. text = text.replace(name+"seconds}", self.getNumericPronounce(dt.second) )
  116. text = text.replace(name+"second}", self.getNumericPronounce(dt.second) )
  117. text = text.replace(name+"}", self.getDateString(dt) )
  118. text = text.replace(name+"moonphase}", mp.phase(time=dt)["name"] )
  119. return text
  120. def getRandomWord(self, items:list) -> str:
  121. if len(items) > 0:
  122. return random.choice(items)
  123. else:
  124. return ""
  125. def readReplacer(self):
  126. tmp = {}
  127. with open("text/Replacer.json") as json_file:
  128. data = json.load(json_file)
  129. for k in data:
  130. tmp[k] = list()
  131. add = True
  132. for i in data[k]:
  133. if "mood_required" in i:
  134. statKeys = ["angry","annoyed","aroused","bored","compfortable","depressive","energy","excited","exhausted",
  135. "freezy","funny","happyness","hot","humanity","hungry","intelligent","irritated","lonely","naiv",
  136. "playful","sad","shy","sleepy","soziality","temperate","toLoud","toQuiet","usefull","useless"]
  137. for sk in statKeys:
  138. if sk+"_max" in i["mood_required"] and i["mood_required"][sk+"_max"] <= getattr(self.stats.deviceStats,sk):
  139. add = False
  140. break
  141. if sk+"_min" in i["mood_required"] and i["mood_required"][sk+"_min"] >= getattr(self.stats.deviceStats,sk):
  142. add = False
  143. break
  144. if add == True and "text" in i:
  145. for t in i["text"]:
  146. tmp[k].append(t)
  147. self.replacer = tmp
  148. @staticmethod
  149. def getWeekDay(weekday:int) -> str:
  150. weekdays = [
  151. "Sonntag",
  152. "Montag",
  153. "Dienstag",
  154. "Mittwoch",
  155. "Donnerstag",
  156. "Freitag",
  157. "Samstag",
  158. "Sonntag"
  159. ]
  160. return weekdays[weekday]
  161. @staticmethod
  162. def getMonthName(month:int) -> str:
  163. monthnames = [
  164. "",
  165. "Januar",
  166. "Februar",
  167. "März",
  168. "April",
  169. "Mai",
  170. "Juni",
  171. "Juli",
  172. "August",
  173. "September",
  174. "Oktober",
  175. "November",
  176. "Dezember"
  177. ]
  178. return monthnames[month]
  179. @staticmethod
  180. def getNumericPronounce(num:float, decimals:int = 2, type:int = NummericPronounce.Normal) -> str:
  181. ''' Formats a integer or floating point value into a readable string
  182. num:float - The Number that should be writeable
  183. decimals:int - the amount of decimals (max 6)
  184. Range: -999,999,999.999999 to 999,999,999.999999
  185. Returns :str'''
  186. if type == NummericPronounce.Year:
  187. s2=""
  188. if num<0:
  189. num*=-1
  190. s2=" vor Christus"
  191. if num>=1300 and num<2200:
  192. num3 = math.floor(num/100)
  193. s = Text.getNumericPronounce(num3)
  194. num2 = num % 100
  195. if(num2>9):
  196. s += " " + Text.getNumericPronounce(num2)
  197. else:
  198. s += " null " + Text.getNumericPronounce(num2 % 10)
  199. return s+s2
  200. else:
  201. # Check for negative numbers
  202. if num<0:
  203. return "Minus " + Text.getNumericPronounce(num * -1)
  204. # Check for decimal
  205. if math.floor(num)!=math.ceil(num):
  206. if decimals<1:
  207. num=math.floor(num)
  208. else:
  209. s = Text.getNumericPronounce(math.floor(num))
  210. num -= math.floor(num)
  211. s+=" Komma"
  212. s+= " " + Text.getNumericPronounce(math.floor(num*10)%10)
  213. if decimals>=2: s+= " " + Text.getNumericPronounce(math.floor(num*100)%10)
  214. if decimals>=3: s+= " " + Text.getNumericPronounce(math.floor(num*1000)%10)
  215. if decimals>=4: s+= " " + Text.getNumericPronounce(math.floor(num*10000)%10)
  216. if decimals>=5: s+= " " + Text.getNumericPronounce(math.floor(num*100000)%10)
  217. if decimals>=6: s+= " " + Text.getNumericPronounce(math.floor(num*1000000)%10)
  218. return s
  219. mod = num%10
  220. zehner=(num-mod) % 100
  221. hunderter=(num-mod-zehner) % 1000
  222. tausender=(num-mod-zehner-hunderter) % 1000000
  223. millonener=(num-mod-zehner-hunderter-tausender) % 1000000000
  224. if num==0: return "null"
  225. elif num==1: return "eins" # handels 1 only
  226. elif num==2: return "zwei" # handels 2, 200, 302, 2.000, 2.000.000
  227. elif num==3: return "drei"
  228. elif num==4: return "vier"
  229. elif num==5: return "fünf"
  230. elif num==6: return "sechs"
  231. elif num==7: return "sieben"
  232. elif num==8: return "acht"
  233. elif num==9: return "neun"
  234. elif num==10: return "zehn"
  235. elif num==11: return "elf"
  236. elif num==12: return "zwölf"
  237. elif num<=19: return Text.getNumericPronounce(mod)+"zehn"
  238. elif num==20: return "zwanzig"
  239. elif num==30: return "dreissig"
  240. elif num==60: return "sechzig"
  241. elif num==70: return "siebzig"
  242. elif num<=99 and mod == 0: return Text.getNumericPronounce(zehner/10)+"zig"
  243. elif num<=99 and mod == 1: return "einund"+Text.getNumericPronounce(zehner) # handels 21, 31, 41, 51, ...
  244. elif num<=99 and mod > 1: return Text.getNumericPronounce(mod) + "und"+ Text.getNumericPronounce(zehner) #handels 22, 23, 24, 25, ... 32, 33, 34, ..., 42, 53, ....
  245. elif num==100: return "einhundert" # handels 100
  246. elif num<=199: return "einhundert" + Text.getNumericPronounce(num%100) # handels 101, 102, 103, ...
  247. elif num<=999 and num%100==0: return Text.getNumericPronounce(hunderter/100)+"hundert" # handels 200, 300, 400, 500, 600, 700, 800, 900
  248. elif num<=999: return Text.getNumericPronounce(hunderter/100)+"hundert"+Text.getNumericPronounce(num%100) # handels 201, 202, ... 301, 302
  249. elif num==1000: return "eintausend"
  250. elif num==10000: return "zehntausend"
  251. elif num==100000: return "einhunderttausend"
  252. elif num==1000000: return "eine millionen"
  253. elif num<=1999: return "eintausend"+Text.getNumericPronounce(num%1000)
  254. elif num<=999999 and num%1000==0: return Text.getNumericPronounce(tausender/1000)+"tausend" # handels 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000
  255. elif num<=999999: return Text.getNumericPronounce(tausender/1000)+"tausend "+Text.getNumericPronounce(num%1000)
  256. elif num<=1999999: return "eine millionen "+Text.getNumericPronounce(millonener%1000000)
  257. elif num<=999999999 and num%1000000==0: return Text.getNumericPronounce(millonener/1000000)+" millionen" # handels 2mio, 3mio, 4mio, 5mio, 6mio, 7mio, 8mio, 9mio
  258. elif num<=999999999: return Text.getNumericPronounce(millonener/1000000)+" millionen "+Text.getNumericPronounce(num%1000000)
  259. else: print("ErrNum: "+num)
  260. @staticmethod
  261. def getNumericDottedPronounce(num:int) -> str:
  262. if num==1:
  263. return "erste"
  264. elif num==3:
  265. return "dritte"
  266. elif num==8:
  267. return "achte"
  268. elif num>= 20:
  269. return Text.getNumericPronounce(num)+"ste"
  270. else:
  271. return Text.getNumericPronounce(num)+"te"
  272. @staticmethod
  273. def getDateString(date, WeekDay:bool = True, Year:bool = True) -> str:
  274. if WeekDay and Year:
  275. return Text.getWeekDay(date.weekday())+", der "+Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)+" "+Text.getNumericPronounce(date.year, 0, NummericPronounce.Year)
  276. pass
  277. elif WeekDay:
  278. return Text.getWeekDay(date.weekday())+", der "+Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)
  279. elif Year:
  280. return Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)+" "+Text.getNumericPronounce(date.year, 0, NummericPronounce.Year)
  281. else:
  282. return Text.getNumericDottedPronounce(date.day)+" "+Text.getMonthName(date.month)
  283. @staticmethod
  284. def getTimeString(time, Seconds:bool=False, Use24:bool=False) -> str:
  285. if Seconds:
  286. return Text.getTimeString(time,False,Use24)+" und " + time.seconds+" Sekunden"
  287. else:
  288. min = time.minute
  289. sur=""
  290. surn=""
  291. if Use24:
  292. hour=Text.getNumericPronounce(time.hour)
  293. hourn=Text.getNumericPronounce((time.hour+1)%24)
  294. else:
  295. hour=Text.getNumericPronounce(time.hour%12)
  296. hourn=Text.getNumericPronounce((time.hour+1)%12)
  297. if time.hour<5 or time.hour>21: sur=" Nachts"
  298. elif time.hour<11: sur=" Morgens"
  299. elif time.hour<16: sur=" Mittags"
  300. elif time.hour<19: sur=" Nachmittags"
  301. else: sur=" Abends"
  302. if time.hour<4 or time.hour>20: surn=" Nachts"
  303. elif time.hour<10: surn=" Morgens"
  304. elif time.hour<15: surn=" Mittags"
  305. elif time.hour<18: surn=" Nachmittags"
  306. else: surn=" Abends"
  307. if time.hour==23:
  308. shour=hour
  309. shourn="Mitternacht"
  310. elif time==0:
  311. shour="Mitternacht"
  312. shourn=hourn
  313. else:
  314. shour=hour
  315. shourn=hourn
  316. if min==0:
  317. return "punkt "+shour+sur
  318. elif min==30:
  319. return "halb "+shourn+surn
  320. elif min>=27 and min<30:
  321. return "kurz vor halb "+shourn+surn
  322. elif min>30 and min<=33:
  323. return "kurz nach halb "+shourn+surn
  324. elif min==15:
  325. return "viertel nach "+shour+sur
  326. elif min==45:
  327. return "viertel vor "+shourn+surn
  328. elif min<=3:
  329. return "kurz nach "+shour+sur
  330. elif min>=37:
  331. return "kurz vor "+shourn+surn
  332. else:
  333. return hour+" Uhr "+Text.getNumericPronounce(min)+sur