33import json
44from functools import wraps
55from datetime import datetime
6- from sc2reader import log_utils
6+ from sc2reader . log_utils import loggable
77
88from functools import wraps
9+ from bisect import bisect_left
10+
911def plugin (func ):
1012 @wraps (func )
1113 def wrapper (** options ):
@@ -26,28 +28,45 @@ def default(self, obj):
2628
2729class GameState (dict ):
2830 def __init__ (self , initial_state ):
31+ self ._frames = list ()
32+ self ._frameset = set ()
2933 self [0 ] = initial_state
3034
3135 def __getitem__ (self , frame ):
3236 if frame in self :
3337 return super (GameState , self ).__getitem__ (frame )
3438
35- # If this particular key doesn't exist, create it
36- prev_frame = sorted (filter (lambda key : key < frame , self .keys ()))[- 1 ]
39+ # Get the previous frame from our sorted frame list
40+ # bisect_left returns the left most key where an item is
41+ # less than or equal to the value in that key. If it is
42+ # less than we need to subtract 1
43+ key = bisect_left (self ._frames , frame )
44+ if key == len (self ._frames ) or self ._frames [key ] > frame :
45+ prev_frame = self ._frames [key - 1 ]
46+ else :
47+ prev_frame = self ._frames [key ]
48+
49+ # Copy the previous state and use it as our basis here
3750 state = self [prev_frame ].copy ()
3851 self [frame ] = state
3952 return state
4053
54+ def __setitem__ (self , frame , value ):
55+ if frame not in self ._frameset :
56+ self ._frames .insert (bisect_left (self ._frames , frame ), frame )
57+ self ._frameset .add (frame )
58+
59+ super (GameState , self ).__setitem__ (frame , value )
60+
4161
62+ @loggable
4263class UnitSelection (object ):
43- def __init__ (self , * new_objects ):
44- self .logger = log_utils .get_logger (UnitSelection )
45- self .objects = list ()
46- self .select (new_objects )
64+ def __init__ (self , objects = None ):
65+ self .objects = objects or list ()
4766
4867 def select (self , new_objects ):
49- object_set = set (self .objects + list (new_objects ))
50- self .objects = sorted (object_set , key = lambda obj : obj .id )
68+ new_set = set (self .objects + list (new_objects ))
69+ self .objects = sorted (new_set , key = lambda obj : obj .id )
5170
5271 def deselect (self , mode , data ):
5372 if mode == 0x01 :
@@ -71,7 +90,7 @@ def __str__(self):
7190 return ', ' .join (str (obj ) for obj in self .objects )
7291
7392 def copy (self ):
74- return UnitSelection (* self .objects )
93+ return UnitSelection (self .objects [:] )
7594
7695
7796class PlayerSelection (dict ):
@@ -82,5 +101,5 @@ def __init__(self):
82101 def copy (self ):
83102 new = PlayerSelection ()
84103 for bank , selection in self .iteritems ():
85- new [bank ] = UnitSelection (* selection .objects )
104+ new [bank ] = UnitSelection (selection .objects [:] )
86105 return new
0 commit comments