main.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import datetime
  2. import psycopg2.extras
  3. import model
  4. from pprint import pprint
  5. import time
  6. import database
  7. import sys
  8. import view
  9. if __name__ == '__main__':
  10. row = -1
  11. if len(sys.argv) > 1:
  12. try:
  13. row = int(sys.argv[1])
  14. except ValueError:
  15. sys.exit(1)
  16. broadcast = True
  17. if len(sys.argv) > 2:
  18. broadcast = False
  19. start = time.time()
  20. db = database.db
  21. race_days_global = model.scrape_main_page(row)
  22. interim = time.time()
  23. # print('interim 1 {}'.format(interim - start))
  24. # pprint(race_days_global)
  25. race_days = []
  26. raw_data_dict = {}
  27. for race_day in race_days_global:
  28. raw_data = model.get_raw_scratchings(race_day)
  29. race_day_details = model.process_raw_data(raw_data, race_day)
  30. race_days.append(race_day_details)
  31. raw_data_dict[race_day.name] = raw_data
  32. interim = time.time()
  33. # print('interim 2 {}'.format(interim - start))
  34. # pprint(race_days)
  35. for race_day in race_days:
  36. if not raw_data_dict or not race_day:
  37. # raw_data_dict may be empty when there is no data available (yet)
  38. continue
  39. raw_data = raw_data_dict[race_day.name]
  40. scratchings = model.get_scratching_details(raw_data, race_day)
  41. if not scratchings:
  42. # model.get_scratchings_details may return empty
  43. continue
  44. # retrieve previous stored scratching for this venue / day
  45. query = "SELECT * FROM horses WHERE venue = %s AND race_date = %s;"
  46. db.commit()
  47. cur1 = db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
  48. cur1.execute(query, (race_day.name, race_day.date))
  49. db_data_query1 = cur1.fetchall()
  50. # print(' 54. len(db_data): {}'.format(len(db_data)))
  51. # print(' 55. type(db_data): {}'.format(type(db_data)))
  52. # pprint(db_data)
  53. cur1.close()
  54. # compare retrieved scratchings with new data
  55. scratchings_for_database = []
  56. messages = []
  57. for scratching in scratchings:
  58. found_in_database = False
  59. # if db_data is None:
  60. # print(' 62. Caught db_data is None')
  61. # found_in_database = False
  62. # else:
  63. for row in db_data_query1:
  64. # print('row: ', end = '')
  65. # print(type(row))
  66. # print(row)
  67. # if type(row) == 'datetime.time':
  68. # continue
  69. try:
  70. # if not hasattr(db_data, 'name'):
  71. # continue
  72. date_in_db_row_formatted = row.race_date.strftime('%Y-%m-%d')
  73. if (
  74. scratching.date == date_in_db_row_formatted and
  75. scratching.venue == row.venue and
  76. int(scratching.race) == int(row.race) and
  77. scratching.horse == row.horse
  78. ):
  79. message_string = 'Horse found: date = {}, venue = {}, race = {}, horse = {}'
  80. message = message_string.format(scratching.date,
  81. scratching.venue,
  82. scratching.race,
  83. scratching.horse)
  84. # print(message)
  85. # print(row)
  86. found_in_database = True
  87. except AttributeError as ae:
  88. print(ae)
  89. print(' 94. row: ', end='')
  90. print(row)
  91. pprint(db_data_query1)
  92. continue
  93. if not found_in_database:
  94. # report new scratching
  95. date_object = datetime.datetime.strptime(scratching.date, "%Y-%m-%d").date()
  96. day_abbr = date_object.strftime('%a')
  97. query = """
  98. SELECT start_time, utctime, torn FROM race_program
  99. WHERE race_date = %s AND
  100. venue = %s AND
  101. race = %s;
  102. """
  103. cur2 = db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
  104. cur2.execute(query, (scratching.date, scratching.venue, scratching.race))
  105. db_data_query2 = cur2.fetchone()
  106. cur2.close()
  107. if db_data_query2 is None or len(db_data_query2) == 0:
  108. print('106. cursor.execute(query, (scratching.date, scratching.venue, scratching.race))')
  109. print('107. cursor.execute({}, ({}, {}, {}))'.format(
  110. query, scratching.date, scratching.venue, scratching.race
  111. ))
  112. print('110. No race found')
  113. continue
  114. flag = ''
  115. if db_data_query2.torn:
  116. flag = 'FLAGGED!! '
  117. message_string = '{}venue = {} {} {}-{} | race = {} starts at {} | {} UTC | horse = {}'
  118. message = message_string.format(flag,
  119. day_abbr,
  120. scratching.date,
  121. scratching.state,
  122. scratching.venue,
  123. scratching.race,
  124. db_data_query2.start_time.strftime('%H:%M'),
  125. db_data_query2.utctime.strftime('%H:%M'),
  126. scratching.horse)
  127. print(message)
  128. if broadcast:
  129. messages.append(message)
  130. # view.broadcast(message)
  131. # store new scratching
  132. scratchings_for_database.append((scratching.venue, scratching.date,
  133. scratching.race, scratching.horse))
  134. long_message = ''
  135. for this_message in messages:
  136. # Append message if possible
  137. if len(long_message) + len(this_message) < 5997:
  138. long_message += '\n' + this_message
  139. else:
  140. # Send long message (max 6k characters)
  141. view.broadcast(long_message)
  142. long_message = this_message
  143. # Send only or last message
  144. if len(this_message) > 0:
  145. view.broadcast(this_message)
  146. this_message = ''
  147. query = """INSERT INTO horses(venue, race_date, race, horse)
  148. VALUES(%s, %s, %s, %s)
  149. ON CONFLICT(venue, race_date, race, horse) DO NOTHING;"""
  150. cur3 = db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
  151. for database_entry in scratchings_for_database:
  152. cur3.execute(query, database_entry)
  153. print('Stored: {}'.format(database_entry))
  154. cur3.close()
  155. db.commit()
  156. db.close()
  157. interim = time.time()
  158. # print('interim 3 {}'.format(interim - start))