fork download
  1. from threading import Thread
  2. from time import sleep
  3.  
  4. class Knob:
  5. def __init__(self, d):
  6. self.__door = d
  7. self.__latched = True
  8.  
  9. @property
  10. def is_latched_off(self):
  11. return not self.__latched
  12.  
  13. def turn(self):
  14. self.__latched = False
  15.  
  16. def unturn(self):
  17. if self.__door.is_close:
  18. self.__latched = True
  19.  
  20. class Door:
  21. def __init__(self):
  22. self.knob = Knob(self)
  23. self.__closed = True
  24.  
  25. @property
  26. def is_close(self):
  27. return self.__closed
  28.  
  29. @property
  30. def is_open(self):
  31. return not self.is_close
  32.  
  33. @property
  34. def can_be_open(self):
  35. return self.is_open or self.knob.is_latched_off
  36.  
  37. def be_open(self):
  38. if self.can_be_open:
  39. self.__closed = False
  40.  
  41. def be_close(self):
  42. self.__closed = True
  43. self.knob.unturn()
  44.  
  45. def push(self):
  46. self.be_open()
  47.  
  48. def pull(self):
  49. self.be_close()
  50.  
  51.  
  52. door1 = Door()
  53. print("door1 is a Door...")
  54. door1.knob.turn()
  55. print("door1.knob.turn(); door1.can_be_open => {0}".format(door1.can_be_open))
  56. door1.knob.unturn()
  57. print("door1.knob.unturn(); door1.can_be_open => {0}".format(door1.can_be_open))
  58. door1.push()
  59. print("door1.push(); door1.is_open => {0}".format(door1.is_open))
  60. door1.knob.turn(); door1.push()
  61. print("door1.knob.turn(); door1.push(); door1.is_open => {0}".format(door1.is_open))
  62. door1.pull()
  63. print("door1.pull(); door1.is_close => {0}".format(door1.is_close))
  64. print("door1.can_be_open => {0}\n".format(door1.can_be_open))
  65.  
  66.  
  67. class DoorCloserPull(Thread):
  68. def __init__(self, door):
  69. super().__init__()
  70. self.__door = door
  71. self.expired = None
  72.  
  73. def run(self):
  74. self.expired = False
  75. sleep(self.__door.delay_sec)
  76. if not self.expired:
  77. self.expired = True
  78. self.__door.pull()
  79.  
  80. class DoorCloserMixin:
  81. def __init__(self, *args, **kwargs):
  82. super().__init__(*args, **kwargs)
  83. self.__delay_sec = 0.3
  84. self.__delayed_pull = None
  85.  
  86. @property
  87. def delay_sec(self):
  88. return self.__delay_sec
  89.  
  90. @delay_sec.setter
  91. def delay_sec(self, value):
  92. self.__delay_sec = value
  93. self.exec_delayed_pull()
  94.  
  95. def exec_delayed_pull(self):
  96. if self.is_open:
  97. if self.__delayed_pull and not self.__delayed_pull.expired:
  98. self.__delayed_pull.expired = True
  99. self.__delayed_pull = DoorCloserPull(self)
  100. self.__delayed_pull.daemon = True
  101. self.__delayed_pull.start()
  102.  
  103. def push(self):
  104. super().push()
  105. self.exec_delayed_pull()
  106.  
  107. class DoorWithCloser(DoorCloserMixin, Door):
  108. pass
  109.  
  110.  
  111. door2 = DoorWithCloser()
  112. print("door2 is a DoorWithCloser with {0} seconds delay ...".format(door2.delay_sec))
  113. door2.knob.turn(); door2.push()
  114. print("door2.knob.turn(); door2.push(); door2.is_open => {0}".format(door2.is_open))
  115. print("0.1 second after", end='')
  116. sleep(0.1)
  117. print(", door2.is_open => {0}".format(door2.is_open))
  118. print("0.4 seconds after", end='')
  119. sleep(0.3)
  120. print(", door2.is_close => {0}".format(door2.is_close))
  121. door2.knob.turn(); door2.push(); door2.delay_sec = 0.6
  122. print("door2.knob.turn(); door2.push(); door2.delay_sec = 0.6; door2.is_open => {0}".format(door2.is_open))
  123. print("0.4 seconds after", end='')
  124. sleep(0.4)
  125. print(", door2.is_close => {0}".format(door2.is_close))
  126. print("0.7 seconds after", end='')
  127. sleep(0.3)
  128. print(", door2.is_close => {0}\n".format(door2.is_close))
  129.  
  130.  
  131. class DoorStopperMixin:
  132. def __init__(self, *args, **kwargs):
  133. super().__init__(*args, **kwargs)
  134. self.__stoppered = False
  135.  
  136. @property
  137. def is_stoppered(self):
  138. return self.__stoppered
  139.  
  140. def be_stoppered_on(self):
  141. self.__stoppered = True
  142.  
  143. def be_stoppered_off(self):
  144. self.__stoppered = False
  145.  
  146. def pull(self):
  147. if not self.is_stoppered:
  148. super().pull()
  149.  
  150. def push(self):
  151. self.__stoppered = False
  152. super().push()
  153.  
  154. class DoorWithStopper(DoorStopperMixin, Door):
  155. pass
  156.  
  157.  
  158. door3 = DoorWithStopper()
  159. print("door3 is a DoorWithStopper...")
  160. door3.knob.turn(); door3.push()
  161. print("door3.knob.turn(); door3.push(); door3.is_open => {0}".format(door3.is_open))
  162. door3.be_stoppered_on(); door3.pull()
  163. print("door3.be_stoppered_on(); door3.pull(); door3.is_close => {0}".format(door3.is_close))
  164. door3.be_stoppered_off(); door3.pull()
  165. print("door3.be_stoppered_off(); door3.pull(); door3.is_close => {0}".format(door3.is_close))
  166. door3.knob.turn(); door3.push()
  167. print("door3.knob.turn(); door3.push(); door3.is_open => {0}".format(door3.is_open))
  168. door3.be_stoppered_on(); door3.pull()
  169. print("door3.be_stoppered_on(); door3.pull(); door3.is_close => {0}".format(door3.is_close))
  170. door3.push(); door3.pull()
  171. print("door3.push(); door3.pull(); door3.is_close => {0}\n".format(door3.is_close))
  172.  
  173.  
  174. class DoorWithCloserStopper(DoorCloserMixin, DoorStopperMixin, Door):
  175. def be_stoppered_off(self):
  176. super().be_stoppered_off()
  177. self.exec_delayed_pull()
  178.  
  179.  
  180. door4 = DoorWithCloserStopper()
  181. print("door4 is a DoorWithCloserStopper with {0} seconds delay ...".format(door4.delay_sec))
  182. door4.knob.turn(); door4.push()
  183. print("door4.knob.turn(); door4.push(); door4.is_open => {0}".format(door4.is_open))
  184. door4.be_stoppered_on()
  185. print("door4.be_stoppered_on(); 0.4 seconds after", end='')
  186. sleep(0.4)
  187. print(", door4.is_open => {0}".format(door4.is_open))
  188. door4.be_stoppered_off()
  189. print("door4.be_stoppered_off(); 0.4 seconds after", end='')
  190. sleep(0.4)
  191. print(", door4.is_close => {0}".format(door4.is_close))
  192. door4.knob.turn(); door4.push()
  193. print("door4.knob.turn(); door4.push(); door4.is_open => {0}".format(door4.is_open))
  194. door4.be_stoppered_on()
  195. print("door4.be_stoppered_on(); 0.4 seconds after", end='')
  196. sleep(0.4)
  197. print(", door4.is_open => {0}".format(door4.is_open))
  198. door4.push()
  199. print("door4.push(); 0.4 seconds after", end='')
  200. sleep(0.4)
  201. print(", door4.is_close => {0}\n".format(door4.is_close))
  202.  
Success #stdin #stdout 0.02s 165952KB
stdin
Standard input is empty
stdout
door1 is a Door...
door1.knob.turn(); door1.can_be_open => True
door1.knob.unturn(); door1.can_be_open => False
door1.push(); door1.is_open => False
door1.knob.turn(); door1.push(); door1.is_open => True
door1.pull(); door1.is_close => True
door1.can_be_open => False

door2 is a DoorWithCloser with 0.3 seconds delay ...
door2.knob.turn(); door2.push(); door2.is_open => True
0.1 second after, door2.is_open => True
0.4 seconds after, door2.is_close => True
door2.knob.turn(); door2.push(); door2.delay_sec = 0.6; door2.is_open => True
0.4 seconds after, door2.is_close => False
0.7 seconds after, door2.is_close => True

door3 is a DoorWithStopper...
door3.knob.turn(); door3.push(); door3.is_open => True
door3.be_stoppered_on(); door3.pull(); door3.is_close => False
door3.be_stoppered_off(); door3.pull(); door3.is_close => True
door3.knob.turn(); door3.push(); door3.is_open => True
door3.be_stoppered_on(); door3.pull(); door3.is_close => False
door3.push(); door3.pull(); door3.is_close => True

door4 is a DoorWithCloserStopper with 0.3 seconds delay ...
door4.knob.turn(); door4.push(); door4.is_open => True
door4.be_stoppered_on(); 0.4 seconds after, door4.is_open => True
door4.be_stoppered_off(); 0.4 seconds after, door4.is_close => True
door4.knob.turn(); door4.push(); door4.is_open => True
door4.be_stoppered_on(); 0.4 seconds after, door4.is_open => True
door4.push(); 0.4 seconds after, door4.is_close => True