switch from popen2 to subprocess (fix deprecation warnings)
[uccvend-vendserver.git] / sql-edition / servers / Idler.py
1 #!/usr/bin/env python
2
3 import string, time, os
4 from subprocess import Popen, PIPE
5 from random import random
6 from MessageKeeper import MessageKeeper
7
8 orderings = None
9
10 IDLER_TEXT_SPEED=1.8
11
12 class Idler:
13         def __init__(self, v):
14                 self.v = v
15
16         def next(self):
17                 """Displays next stage of the idler. Returns time to the next step"""
18                 return 1
19
20         def reset(self):
21                 """Resets the idler to a known intial state"""
22                 pass
23         
24         def finished(self):
25                 """Returns True if the idler is considered finished"""
26                 return False
27
28         def affinity(self):
29                 """How much we want this idler to be the next one chosen"""
30                 return 1
31
32 class GreetingIdler(Idler):
33         def __init__(self, v, secs_to_greeting = None):
34                 self.v = v
35                 self.secs_to_greeting = secs_to_greeting
36                 self.message_displayed = False
37
38         def next(self):
39                 if not self.secs_to_greeting is None:
40                         x = self.secs_to_greeting
41                         self.secs_to_greeting = None
42                         return x
43
44                 self.v.display('UCC SNACKS')
45                 self.message_displayed = True
46                 return 5
47
48         def reset(self):
49                 self.message_displayed = False
50                 self.secs_to_greeting = None
51
52         def finished(self):
53                 return self.message_displayed
54
55         def affinity(self):
56                 return 0
57
58 class TrainIdler(Idler):
59         def __init__(self, v):
60                 self.idle_state = 0
61                 self.v = v
62
63         def put_shark(self, s, l):
64                 if self.s[l] == ' ':
65                         self.s[l] = s
66                 elif self.s[l] == 'X':
67                         self.s[l] = '*'
68                 else:
69                         self.s[l] = 'X'
70
71         def next(self):
72                 # does the next stage of a dance
73                 self.s = [' ']*10
74                 shark1 = self.idle_state % 18
75                 if shark1 < 9:
76                         self.put_shark('^', shark1)
77                 else:
78                         self.put_shark('^', 18-shark1)
79
80                 shark2 = ((self.idle_state+4) % 36)/2
81                 if shark2 < 9:
82                         self.put_shark('<', shark2)
83                 else:
84                         self.put_shark('<', 18-shark2)
85
86                 shark3 = ((self.idle_state+7) % 54)/3
87                 if shark3 < 9:
88                         self.put_shark('>', 9-shark3)
89                 else:
90                         self.put_shark('>', 9-(18-shark3))
91
92                 train1 = ((self.idle_state%(18*36)))
93                 train1_start = 122
94                 if train1 > train1_start and train1 < train1_start+(10*2):
95                         for i in range(5):
96                                 ptr = i+train1-train1_start-5
97                                 if ptr >= 0 and ptr < 10: self.s[ptr] = '#'
98
99                 train2 = ((self.idle_state%(18*36)))
100                 train2_start = 400
101                 if train2 > train2_start and train2 < train2_start+(10*2):
102                         for i in range(5):
103                                 ptr = i+train2-train2_start-5
104                                 if ptr >= 0 and ptr < 10: self.s[9-ptr] = '#'
105
106                 train3 = ((self.idle_state%(18*36)))
107                 train3_start = 230
108                 if train3 > train3_start and train3 < train3_start+(10*2):
109                         for i in range(10):
110                                 ptr = i+train3-train3_start-10
111                                 if ptr >= 0 and ptr < 10: self.s[ptr] = '-'
112
113                 self.v.display(string.join(self.s, ''))
114                 self.idle_state += 1
115                 self.idle_state %= 18*36*54
116
117         def reset(self):
118                 self.idle_state = 0
119
120 class OrderMaker:
121         def __init__(self, n=8):
122                 self.n = n
123                 self.make_factorials(n)
124         
125         def make_factorials(self, n):
126                 self.factorial = []
127                 a = 1
128                 for i in range(1,n+1):
129                         self.factorial.append(a)
130                         a *= i
131
132         def order(self, index):
133                 used = []
134                 for i in range(0,self.n):
135                         used.append(i)
136                 i = self.n-1
137                 j = 0
138                 res = []
139                 while i >= 0:
140                         a = index/self.factorial[i]
141                         index %= self.factorial[i]
142                         res.append(a+1)
143                         i -= 1
144                         j += 1
145                 for i in range(0,self.n):
146                         tmp = used[res[i]-1]
147                         for j in range(res[i],self.n):
148                                 used[j-1] = used[j]
149                         res[i] = tmp
150                 return res
151
152         def __getitem__(self, i):
153                 return self.order(i)
154
155 class GrayIdler(Idler):
156         def __init__(self, v, one=None, zero=None, reorder=0):
157                 self.bits = 8
158                 self.size = 1 << self.bits
159                 self.i = 0
160                 self.grayCode = 0
161                 self.v = v
162                 self.one = one
163                 self.zero = zero
164                 self.reorder = reorder
165                 global orderings
166                 if not orderings:
167                         orderings = OrderMaker()
168
169         def next(self):
170                 output = self.do_next_state()
171                 # does the next stage of a dance
172                 if self.zero:
173                         output = string.replace(output, "0", self.zero)
174                 if self.one:
175                         output = string.replace(output, "1", self.one)
176                 if self.reorder:
177                         global orderings
178                         newoutput = ""
179                         for i in range(0,8):
180                                 newoutput += output[orderings[self.reorder][i]]
181                         output = newoutput
182                 self.v.display(" %8.8s " % (output))
183                 self.i = (self.i + 1) % self.size
184
185         def do_next_state(self):
186                 self.grayCode = self.i ^ (self.i >> 1)
187                 output = self.dec2bin(self.grayCode)
188
189                 return "0"*(self.bits-len(output))+output
190
191
192         def dec2bin(self,num):
193             """Convert long/integer number to binary string.
194
195             E.g. dec2bin(12) ==> '1100'.
196             
197             from http://starship.python.net/~gherman/playground/decbingray/decbingray.py"""
198
199             assert num >= 0, "Decimal number must be >= 0!"
200
201             # Gracefully handle degenerate case.
202             # (Not really needed, but anyway.)    
203             if num == 0:
204                 return '0'
205
206             # Find highest value bit.
207             val, j = 1L, 1L
208             while val < num:
209                 val, j = val*2L, j+1L
210
211             # Convert.
212             bin = '' 
213             i = j - 1
214             while i + 1L:
215                 k = pow(2L, i)
216                 if num >= k:
217                     bin = bin + '1'
218                     num = num - k
219                 else:
220                     if len(bin) > 0:
221                         bin = bin + '0'
222                 i = i - 1L
223
224             return bin
225
226         def reset(self):
227                 self.i = 0
228                 self.grayCode = 0
229                 if self.reorder:
230                         self.reorder = int(random()*40319)+1
231
232
233 class StringIdler(Idler):
234         def __init__(self, v, text="Hello Cruel World!  ",repeat=True):
235                 self.v = v
236                 self.mk = MessageKeeper(v)
237                 self.text = self.clean_text(text) + "          "
238                 
239                 msg = [("",False, None),(self.text, repeat, IDLER_TEXT_SPEED)]
240                 self.mk.set_messages(msg)
241
242         def clean_text(self, text):
243                 # nothing like a bit of good clean text :)
244                 valid = string.digits \
245                         + string.letters \
246                         + string.punctuation \
247                         + " "
248                 # uppercase it
249                 text = string.upper(text)
250                 clean = ""
251                 for char in text:
252                         if char in valid:
253                                 clean = clean + char
254                         else:
255                                 clean = clean + " "
256                 return clean
257
258         def next(self):
259                 self.mk.update_display()
260
261         def finished(self):     
262                 return self.mk.done()
263
264 class ClockIdler(Idler):
265         def __init__(self, v):
266                 self.v = v
267                 self.last = None
268
269         def next(self):
270                 colonchar = ':'
271                 if int(time.time()*2) & 1: colonchar = ' '
272                 output = time.strftime("%%H%c%%M%c%%S"%(colonchar,colonchar))
273                 if output != self.last:
274                         self.v.display(" %8.8s " % (output))
275                         self.last = output
276
277         def affinity(self):
278                 return 3 
279
280 class FortuneIdler(StringIdler):
281         def __init__(self, v):
282                 fortune = "/usr/games/fortune"
283                 text = "I broke my wookie...."
284                 if os.access(fortune,os.F_OK|os.X_OK):
285                         (lines, unused) = Popen((fortune,), close_fds=True, stdout=PIPE).communicate()
286                         text = string.join(lines)
287                 StringIdler.__init__(self, v, text,repeat=False)
288
289         def affinity(self):
290                 return 20
291
292 class PipeIdler(StringIdler):
293         def __init__(self, v, command, args):
294                 text = "I ate my cookie...."
295                 if os.access(command,os.F_OK|os.X_OK):
296                         (lines, unused) = Popen([command,] + args.split(), close_fds=True, stdout=PIPE).communicate()
297                         text = string.join(lines)
298                 StringIdler.__init__(self, v, text,repeat=False)
299
300         def affinity(self):
301                 return 20
302
303 class FileIdler(StringIdler):
304         def __init__(self, v, thefile=None, repeat=False, affinity=8):
305                 text = "I broke my wookie...."
306                 self._affinity = affinity
307
308                 if file and os.access(thefile,os.F_OK|os.R_OK):
309                         f = file(thefile,'r')
310                         text = string.join(f.readlines())
311                         f.close()
312                 StringIdler.__init__(self, v, text,repeat=repeat)
313
314         def affinity(self):
315                 return self._affinity

UCC git Repository :: git.ucc.asn.au