You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
7.5 KiB

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. use Log, DB;
  5. class Mission extends Model
  6. {
  7. protected $fillable = [
  8. 'hashtag',
  9. ];
  10. public function tweets() {
  11. return $this->hasMany('App\Tweet');
  12. }
  13. private function unique_trimet_transit_lines(Team $team) {
  14. static $cache = [];
  15. if(array_key_exists($team->id, $cache))
  16. return $cache[$team->id];
  17. $tweets = Tweet::where('team_id', $team->id)
  18. ->where('m1_complete', 1)->whereNotNull('m1_transit_line_id')->get();
  19. $lines = [];
  20. foreach($tweets as $tweet) {
  21. if($tweet->m1_transit_line_id && !in_array($tweet->m1_transit_line_id, $lines)) {
  22. $lines[] = $tweet->m1_transit_line_id;
  23. }
  24. }
  25. $cache[$team->id] = count($lines);
  26. return count($lines);
  27. }
  28. private function unique_transit_centers(Team $team, $with_another_team=false) {
  29. static $cache = ['with'=>[], 'without'=>[]];
  30. if(array_key_exists($team->id, $cache[$with_another_team?'with':'without']))
  31. return $cache[$with_another_team?'with':'without'][$team->id];
  32. $query = Tweet::where('team_id', $team->id)->where('m2_complete', 1);
  33. if($with_another_team)
  34. $query = $query->where('m2_with_other_team', 1);
  35. $tweets = $query->get();
  36. $centers = [];
  37. foreach($tweets as $tweet) {
  38. if($tweet->m2_transit_center_id && !in_array($tweet->m2_transit_center_id, $centers)) {
  39. $centers[] = $tweet->m2_transit_center_id;
  40. }
  41. }
  42. $cache[$with_another_team?'with':'without'][$team->id] = count($centers);
  43. return count($centers);
  44. }
  45. private function unique_documents(Team $team) {
  46. static $cache = [];
  47. if(array_key_exists($team->id, $cache))
  48. return $cache[$team->id];
  49. $tweets = Tweet::where('team_id', $team->id)->whereNotNull('m7_document_id')->get();
  50. $documents = [];
  51. foreach($tweets as $tweet) {
  52. if($tweet->m7_document_id && !in_array($tweet->m7_document_id, $documents)) {
  53. $documents[] = $tweet->m7_document_id;
  54. }
  55. }
  56. $cache[$team->id] = count($documents);
  57. return count($documents);
  58. }
  59. private function num_tweets_for_mission(Team $team, $m) {
  60. static $cache = [3=>[], 4=>[], 5=>[], 6=>[]];
  61. if(array_key_exists($team->id, $cache[$m]))
  62. return $cache[$m][$team->id];
  63. $num = Tweet::where('team_id', $team->id)->where('m'.$m.'_complete', 1)->count();
  64. $cache[$m][$team->id] = $num;
  65. return $num;
  66. }
  67. public function complete(Team $team) {
  68. switch($this->id) {
  69. case 1:
  70. // 5 unique trimet transit lines
  71. return $this->unique_trimet_transit_lines($team) >= 5;
  72. case 2:
  73. // 3 unique transit centers
  74. return $this->unique_transit_centers($team) >= 3;
  75. case 3:
  76. case 4:
  77. case 5:
  78. case 6:
  79. return $this->num_tweets_for_mission($team, $this->id) >= 1;
  80. case 7:
  81. return $this->unique_documents($team) >= 3;
  82. }
  83. }
  84. public function progress(Team $team) {
  85. switch($this->id) {
  86. case 1:
  87. return [$this->unique_trimet_transit_lines($team), 5];
  88. case 2:
  89. return [$this->unique_transit_centers($team), 3];
  90. case 3:
  91. case 4:
  92. case 5:
  93. case 6:
  94. return [$this->num_tweets_for_mission($team, $this->id), 1];
  95. case 7:
  96. return [$this->unique_documents($team), 3];
  97. }
  98. return [false,false];
  99. }
  100. public function score(Team $team) {
  101. switch($this->id) {
  102. case 1:
  103. // No points unless they hit 5 trimet transit lines
  104. if($this->complete($team)) {
  105. $score = 50;
  106. // 20 bonus for each line that is not trimet
  107. $tweets = Tweet::where('team_id', $team->id)->where('m1_complete', 1)->whereNotNull('m1_non_trimet')->get();
  108. $lines = [];
  109. foreach($tweets as $tweet) {
  110. if(!in_array($tweet->m1_non_trimet, $lines)) {
  111. $lines[] = $tweet->m1_non_trimet;
  112. }
  113. }
  114. $score += count($lines) * 20;
  115. return $score;
  116. } else {
  117. return 0;
  118. }
  119. break;
  120. case 2:
  121. // No points unless they hit 3 transit centers
  122. if($this->complete($team)) {
  123. $score = 50;
  124. // If they have more than 3 unique transit centers,
  125. // then award bonus points for any beyond the third with another team
  126. $unique_transit_centers = $this->unique_transit_centers($team);
  127. if($unique_transit_centers > 3) {
  128. // Take the total number of transit centers and subtract 3
  129. $total_possible_bonus = $unique_transit_centers - 3;
  130. // Find the number of unique transit centers with another team
  131. $unique_with_another_team = $this->unique_transit_centers($team, true);
  132. // Use the smaller of the two numbers as the bonus
  133. $score += 20 * min($total_possible_bonus, $unique_with_another_team);
  134. }
  135. // Increasing bonus points for additional transit centers
  136. if($unique_transit_centers >= 4) {
  137. $score += 10;
  138. }
  139. if($unique_transit_centers >= 5) {
  140. $score += 20;
  141. }
  142. if($unique_transit_centers >= 6) {
  143. $score += 30;
  144. }
  145. if($unique_transit_centers >= 7) {
  146. $score += (50 * ($unique_transit_centers - 6));
  147. }
  148. // Double points for each transit center that no other team goes to
  149. $this_team_tcs = Tweet::where('team_id', $team->id)->where('m2_complete', 1)
  150. ->distinct()->pluck('m2_transit_center_id')->toArray();
  151. $other_visited_tcs = Tweet::where('team_id', '!=', $team->id)->where('m2_complete', 1)
  152. ->distinct()->pluck('m2_transit_center_id')->toArray();
  153. $distinct_tcs = array_diff($this_team_tcs, $other_visited_tcs);
  154. if(count($distinct_tcs) > 0) {
  155. $score *= 2;
  156. }
  157. return $score;
  158. } else {
  159. return 0;
  160. }
  161. break;
  162. case 3:
  163. case 4:
  164. case 6:
  165. if($this->complete($team)) {
  166. return 50;
  167. } else {
  168. return 0;
  169. }
  170. case 5:
  171. if($this->complete($team)) {
  172. $score = 50;
  173. // +10 if any of their photos are tipping the bus driver
  174. $num = Tweet::where('team_id', $team->id)->where('m5_complete', 1)->where('m5_tip', 1)->count();
  175. if($num > 0)
  176. $score += 10;
  177. return $score;
  178. } else {
  179. return 0;
  180. }
  181. case 7:
  182. if($this->complete($team)) {
  183. $score = 50;
  184. // +5 for each additional photo
  185. $extra_docs = $this->unique_documents($team) - 3;
  186. if($extra_docs > 0) {
  187. $score += $extra_docs * 5;
  188. }
  189. // add bonus points for certain documents
  190. $tweets = DB::table('tweets')->select('m7_document_id', 'm7_documents.points')
  191. ->where('team_id', $team->id)
  192. ->join('m7_documents', 'm7_documents.id', '=', 'tweets.m7_document_id')
  193. ->whereNotNull('m7_document_id')
  194. ->distinct()->get();
  195. foreach($tweets as $tweet) {
  196. $score += $tweet->points;
  197. }
  198. return $score;
  199. } else {
  200. return 0;
  201. }
  202. }
  203. }
  204. }