antiaddiction.py (6791B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\antiaddiction.py 2 import blue 3 import log 4 import uthread 5 import localization 6 import bluepy 7 from eveprefs import prefs, boot 8 from caching.memoize import Memoize 9 from player_messaging.client.ui_message import prompt_player_fsd_dialog 10 from functools import reduce 11 historyVersion = 7 12 13 def OnLogin(): 14 global _savePeriod 15 global _displaySeconds 16 global _watchSpan 17 global _allowedTime 18 global _schedule 19 if boot.region != 'optic' or not AmIUnderage(): 20 return 21 if prefs.GetValue('aaTestTimes', 0): 22 _watchSpan = _testWatchSpan 23 _allowedTime = _testAllowedTime 24 _schedule = _testSchedule 25 _savePeriod = _testSavePeriod 26 _displaySeconds = True 27 else: 28 _watchSpan = _liveWatchSpan 29 _allowedTime = _liveAllowedTime 30 _schedule = _liveSchedule 31 _savePeriod = _liveSavePeriod 32 _displaySeconds = False 33 sessionID = StartSession() 34 uthread.worker('antiaddiction::EndSession', lambda : EndSessionWorker(sessionID)) 35 36 def ActionWrap(action, time): 37 return lambda : action(time) 38 39 t = TimeLeft() 40 for time, action in _schedule: 41 if t <= time: 42 action(t) 43 break 44 else: 45 Schedule(t - time, ActionWrap(action, time)) 46 47 48 class Session: 49 50 def __init__(self, sessionID, startTime, endTime): 51 self.sessionID = sessionID 52 self.start = startTime 53 self.end = endTime 54 55 def Save(self): 56 return '%s:%s:%s' % (self.sessionID, self.start.Seconds(), self.end.Seconds()) 57 58 def Load(cls, s): 59 sessionID, startSecs, endSecs = map(long, s.split(':')) 60 return cls(sessionID, Seconds(startSecs), Seconds(endSecs)) 61 62 Load = classmethod(Load) 63 64 def PreLoad(cls, r): 65 sessionID, startSecs, endSecs = r 66 return cls(sessionID, Seconds(int(str(startSecs)[0:11])), Seconds(int(str(endSecs)[0:11]))) 67 68 PreLoad = classmethod(PreLoad) 69 70 def __repr__(self): 71 return '<session %s (%s secs)>' % (self.sessionID, (self.end - self.start).Seconds()) 72 73 74 def StartSession(): 75 h = LoginHistory(1) 76 if h: 77 sessionID = h[-1].sessionID + 1 78 else: 79 sessionID = 1 80 SaveHistory(h + [Session(sessionID, Now(), Now())]) 81 return sessionID 82 83 84 def EndSessionWorker(sessionID): 85 while True: 86 EndSession(sessionID) 87 blue.pyos.synchro.SleepWallclock(_savePeriod.Milliseconds()) 88 89 90 def EndSession(sessionID): 91 h = LoginHistory() 92 for session in h: 93 if session.sessionID == sessionID: 94 session.end = Now() 95 SaveHistory(h) 96 break 97 else: 98 log.LogError('antiaddiction.EndSession: session not found') 99 100 101 def SaveHistory(h): 102 settings.user.ui.Set(HistoryKey(), map(Session.Save, h)) 103 104 105 def HistoryKey(): 106 return 'aaLoginHistory_%s' % historyVersion 107 108 109 def LoginHistory(init = 0): 110 if init == 1: 111 h = map(Session.PreLoad, GetAccruedTime()) 112 else: 113 h = map(Session.Load, settings.user.ui.Get(HistoryKey(), [])) 114 for session in h[:]: 115 if session.end < ForgetTime(): 116 h.remove(session) 117 118 if h and h[0].start < ForgetTime(): 119 h[0].start = ForgetTime() 120 return h 121 122 123 def KickPlayer(): 124 Schedule(Seconds(20), lambda : bluepy.Terminate(0)) 125 prompt_player_fsd_dialog('AntiAddictionTimeExceeded', {'waitTime': WaitLeft().displayStr()}) 126 bluepy.Terminate(0) 127 128 129 def TimeWarning(timeLeft): 130 accruedTime = _allowedTime - timeLeft 131 prompt_player_fsd_dialog('AntiAddictionTimeWarning', {'accruedTime': accruedTime.displayStr(), 132 'timeLeft': timeLeft.displayStr()}) 133 134 135 def TimeNotify(timeLeft): 136 accruedTime = _allowedTime - timeLeft 137 prompt_player_fsd_dialog('AntiAddictionTimeNotify', {'accruedTime': accruedTime.displayStr()}) 138 139 140 def TimeLeft(): 141 history = LoginHistory() 142 accrued = SumTimes(map(SessionDuration, history)) 143 for start, duration in Blanks(history): 144 accrued += duration 145 excess = accrued - _allowedTime 146 if excess > NoTime(): 147 return start - ForgetTime() + (duration - excess) 148 149 150 def Blanks(history): 151 last = ForgetTime() 152 for session in history: 153 yield (last, session.start - last) 154 last = session.end 155 156 yield (last, Now() - last) 157 158 159 def SumTimes(times): 160 return reduce(Time.__add__, times, NoTime()) 161 162 163 def SessionDuration(s): 164 return s.end - s.start 165 166 167 def Now(): 168 return BlueTime(blue.os.GetWallclockTime()) 169 170 171 def WaitLeft(): 172 return LoginHistory()[0].start - ForgetTime() 173 174 175 def ForgetTime(): 176 return Now() - _watchSpan 177 178 179 def Schedule(time, action): 180 181 def f(): 182 blue.pyos.synchro.SleepWallclock(time.Milliseconds()) 183 action() 184 185 uthread.new(f) 186 187 188 @Memoize 189 def AmIUnderage(): 190 jwtToken = sm.GetService('connection').GetLoginJWT() 191 return sm.RemoteSvc('authentication').AmUnderage(jwtToken) 192 193 194 def GetAccruedTime(): 195 return sm.RemoteSvc('authentication').AccruedTime() 196 197 198 def NoTime(): 199 return Time(0) 200 201 202 def Seconds(s): 203 return Time(s) 204 205 206 def Minutes(m): 207 return Seconds(m * 60) 208 209 210 def Hours(h): 211 return Minutes(h * 60) 212 213 214 def BlueTime(bt): 215 return Time(bt // 10000000) 216 217 218 class Time: 219 220 def __init__(self, secs): 221 self._secs = secs 222 223 def Milliseconds(self): 224 return self._secs * 1000 225 226 def Seconds(self): 227 return self._secs 228 229 def Minutes(self): 230 return self.Seconds() // 60 231 232 def Hours(self): 233 return self.Minutes() // 60 234 235 def __add__(self, other): 236 return Time(self._secs + other._secs) 237 238 def __sub__(self, other): 239 return Time(self._secs - other._secs) 240 241 def __cmp__(self, other): 242 return cmp(self._secs, other._secs) 243 244 def displayStr(self): 245 timeVal = self.Seconds() * const.SEC 246 showTo = 'minute' 247 if _displaySeconds: 248 showTo = 'second' 249 return localization.formatters.FormatTimeIntervalWritten(timeVal, showFrom='year', showTo=showTo) 250 251 def __repr__(self): 252 label = localization.GetByLabel('/Carbon/UI/Common/DateTimeQuantity/DateTimeShort3Elements', value1=int(self.Hours()), value2=int(self.Minutes() % 60), value3=int(self.Seconds() % 60)) 253 return '<Time: %s>' % label 254 255 256 _liveWatchSpan = Hours(24) 257 _testWatchSpan = Minutes(24) 258 _liveAllowedTime = Hours(3) 259 _testAllowedTime = Minutes(3) 260 _liveSchedule = [(NoTime(), lambda blah: KickPlayer()), 261 (Minutes(5), TimeWarning), 262 (Minutes(15), TimeWarning), 263 (Hours(1), TimeWarning), 264 (Hours(2), TimeWarning)] 265 _testSchedule = [(NoTime(), lambda blah: KickPlayer()), 266 (Seconds(5), TimeWarning), 267 (Seconds(15), TimeWarning), 268 (Minutes(1), TimeWarning), 269 (Minutes(2), TimeWarning)] 270 _liveSavePeriod = Minutes(1) 271 _testSavePeriod = Seconds(1)