fork download
  1. import time
  2. import math
  3. class BikeComputer():
  4. MM_IN_AN_INCH = 25.4
  5. MM_IN_A_MILE = 1609344
  6. MM_IN_A_KILOMETER = 1000000
  7. SECONDS_IN_AN_HOUR = 3600
  8. SECONDS_IN_A_MINUTE = 60
  9. MS_IN_A_SECOND = 1000.0000
  10. displayFormat = 'metric'
  11. displayInterval = 1000 # Update display every 1 second
  12. clicks = 0
  13. tripBegin = 0
  14. lastClick = 0
  15. lastDisplay = 0
  16. hertz = 0.0
  17. displayVelocity = 0.0
  18. velocity = 0.0
  19. avgVelocity = 0.0
  20. maxVelocity = 0.0
  21. distance = 0.0
  22. wheelCircumference = 2136.0
  23. wheelDiameter = 680.0
  24.  
  25. def __init__(self, displayFormat):
  26. self.displayFormat = displayFormat
  27. self.clicks = 0
  28. self.lastDisplay = int(time.time() * BikeComputer.MS_IN_A_SECOND)
  29. self.lastClick = int(time.time() * BikeComputer.MS_IN_A_SECOND)
  30. self.tripBegin = int(time.time() * BikeComputer.MS_IN_A_SECOND)
  31. self.hertz = 0.0
  32.  
  33. self.index = 0
  34. self.displayVelocity = 0.0
  35. self.velocity = 0.0
  36. self.avgVelocity = 0.0
  37. self.maxVelocity = 0.0
  38. self.distance = 0.0
  39. self.wheelCircumference = 2136.0 # 700c x 28 according to a Bell cycling computer chart
  40. self.wheelDiameter = self.wheelCircumference / math.pi
  41.  
  42. def update(self, currentTime, pinState):
  43. # get the delta from our last click
  44. clickDelta = max((currentTime - self.lastClick), 1)
  45. # get the delta from our last display
  46. displayDelta = max((currentTime - self.lastDisplay), 1)
  47. if(pinState == True):
  48. self.clicks += 1
  49. # calculate the instantaneous speed
  50. self.hertz = BikeComputer.MS_IN_A_SECOND / clickDelta
  51. # Velocity = hertz * wheel circumference, in mm/s
  52. self.velocity = (self.hertz * self.wheelCircumference)
  53. self.maxVelocity = max(self.velocity,self.maxVelocity)
  54. # Distance travelled = clicks * wheel circumference, in mm
  55. self.distance = self.clicks * self.wheelCircumference
  56. # Update the last click
  57. self.lastClick = currentTime
  58. else:
  59. # decay the speed. We know that you aren't going fast enough to have done the next click yet
  60. self.hertz = min((BikeComputer.MS_IN_A_SECOND / clickDelta), self.hertz)
  61. self.velocity = self.hertz * self.wheelCircumference
  62. # Distance travelled = clicks * wheel circumference, in mm
  63. self.distance = self.clicks * self.wheelCircumference
  64. # If we haven't updated the display in a while, do that now
  65. if(displayDelta > self.displayInterval):
  66. self.updateDisplayVelocity(currentTime);
  67. self.lastDisplay = currentTime
  68.  
  69. def updateDisplayVelocity(self,currentTime):
  70. self.displayVelocity = self.velocity
  71. self.avgVelocity = self.distance / (((currentTime-self.tripBegin)+1)/1000.00)
  72. if(self.displayFormat == 'metric' and (self.displayVelocity / BikeComputer.MM_IN_A_KILOMETER * BikeComputer.SECONDS_IN_AN_HOUR) < 1.0):
  73. self.displayVelocity = 0.0
  74. if(self.displayFormat == 'imperial' and (self.displayVelocity / BikeComputer.MM_IN_A_MILE * BikeComputer.SECONDS_IN_AN_HOUR) < 1.0):
  75. self.displayVelocity = 0.0
  76.  
  77. def getClicks(self):
  78. return str(self.clicks)
  79.  
  80. def getVelocity(self):
  81. if(self.displayFormat == 'metric'):
  82. return (self.velocity / BikeComputer.MM_IN_A_KILOMETER) * BikeComputer.SECONDS_IN_AN_HOUR
  83. else:
  84. return (self.velocity / BikeComputer.MM_IN_A_MILE) * BikeComputer.SECONDS_IN_AN_HOUR
  85.  
  86. def getDisplayVelocity(self):
  87. if(self.displayFormat == 'metric'):
  88. return (self.displayVelocity / BikeComputer.MM_IN_A_KILOMETER) * BikeComputer.SECONDS_IN_AN_HOUR
  89. else:
  90. return (self.displayVelocity / BikeComputer.MM_IN_A_MILE) * BikeComputer.SECONDS_IN_AN_HOUR
  91.  
  92. def getAverageVelocity(self):
  93. if(self.displayFormat == 'metric'):
  94. return (self.avgVelocity / BikeComputer.MM_IN_A_KILOMETER) * BikeComputer.SECONDS_IN_AN_HOUR
  95. else:
  96. return (self.avgVelocity / BikeComputer.MM_IN_A_MILE) * BikeComputer.SECONDS_IN_AN_HOUR
  97.  
  98. def getMaxVelocity(self):
  99. if(self.displayFormat == 'metric'):
  100. return (self.maxVelocity / BikeComputer.MM_IN_A_KILOMETER) * BikeComputer.SECONDS_IN_AN_HOUR
  101. else:
  102. return (self.maxVelocity / BikeComputer.MM_IN_A_MILE) * BikeComputer.SECONDS_IN_AN_HOUR
  103.  
  104. def getDistance(self):
  105. if(self.displayFormat == 'metric'):
  106. return (self.distance / BikeComputer.MM_IN_A_KILOMETER)
  107. else:
  108. return (self.distance / BikeComputer.MM_IN_A_MILE)
  109.  
  110. def getFormattedWheelCircumference(self):
  111. if(self.displayFormat == 'metric'):
  112. return str(self.wheelCircumference) + ' mm'
  113. else:
  114. return str(round(self.wheelCircumference / BikeComputer.MM_IN_AN_INCH,3)) + ' in'
  115.  
  116. def getFormattedWheelDiameter(self):
  117. if(self.displayFormat == 'metric'):
  118. return str(self.wheelDiameter) + ' mm'
  119. else:
  120. return str(round(self.wheelDiameter / BikeComputer.MM_IN_AN_INCH,3)) + ' in'
  121.  
  122. def getFormattedVelocity(self):
  123. if(self.displayFormat == 'metric'):
  124. return str(round((self.velocity / BikeComputer.MM_IN_A_KILOMETER) * BikeComputer.SECONDS_IN_AN_HOUR, 1)) + 'kmph'
  125. else:
  126. return str(round((self.velocity / BikeComputer.MM_IN_A_MILE) * BikeComputer.SECONDS_IN_AN_HOUR, 1)) + 'mph'
  127.  
  128. def getFormattedDisplayVelocity(self):
  129. if(self.displayFormat == 'metric'):
  130. return str(round((self.displayVelocity / BikeComputer.MM_IN_A_KILOMETER) * BikeComputer.SECONDS_IN_AN_HOUR, 1)) + 'kmph'
  131. else:
  132. return str(round((self.displayVelocity / BikeComputer.MM_IN_A_MILE) * BikeComputer.SECONDS_IN_AN_HOUR, 1)) + 'mph'
  133.  
  134. def getFormattedAvgVelocity(self):
  135. if(self.displayFormat == 'metric'):
  136. return str(round((self.avgVelocity / BikeComputer.MM_IN_A_KILOMETER) * BikeComputer.SECONDS_IN_AN_HOUR, 1)) + 'kmph'
  137. else:
  138. return str(round((self.avgVelocity / BikeComputer.MM_IN_A_MILE) * BikeComputer.SECONDS_IN_AN_HOUR, 1)) + 'mph'
  139.  
  140. def getFormattedDistance(self):
  141. if(self.displayFormat == 'metric'):
  142. return str(round((self.distance / BikeComputer.MM_IN_A_KILOMETER),1))+'km'
  143. else:
  144. return str(round((self.distance / BikeComputer.MM_IN_A_MILE),3))+'mi'
  145.  
  146.  
Success #stdin #stdout 0.1s 14056KB
stdin
Standard input is empty
stdout
Standard output is empty