hasMany('App\Tweet'); } private function unique_trimet_transit_lines(Team $team) { static $cache = []; if(array_key_exists($team->id, $cache)) return $cache[$team->id]; $tweets = Tweet::where('team_id', $team->id) ->where('m1_complete', 1)->whereNotNull('m1_transit_line_id')->get(); $lines = []; foreach($tweets as $tweet) { if($tweet->m1_transit_line_id && !in_array($tweet->m1_transit_line_id, $lines)) { $lines[] = $tweet->m1_transit_line_id; } } $cache[$team->id] = count($lines); return count($lines); } private function unique_transit_centers(Team $team, $with_another_team=false) { static $cache = ['with'=>[], 'without'=>[]]; if(array_key_exists($team->id, $cache[$with_another_team?'with':'without'])) return $cache[$with_another_team?'with':'without'][$team->id]; $query = Tweet::where('team_id', $team->id)->where('m2_complete', 1); if($with_another_team) $query = $query->where('m2_with_other_team', 1); $tweets = $query->get(); $centers = []; foreach($tweets as $tweet) { if($tweet->m2_transit_center_id && !in_array($tweet->m2_transit_center_id, $centers)) { $centers[] = $tweet->m2_transit_center_id; } } $cache[$with_another_team?'with':'without'][$team->id] = count($centers); return count($centers); } private function unique_documents(Team $team) { static $cache = []; if(array_key_exists($team->id, $cache)) return $cache[$team->id]; $tweets = Tweet::where('team_id', $team->id)->whereNotNull('m7_document_id')->get(); $documents = []; foreach($tweets as $tweet) { if($tweet->m7_document_id && !in_array($tweet->m7_document_id, $documents)) { $documents[] = $tweet->m7_document_id; } } $cache[$team->id] = count($documents); return count($documents); } private function num_tweets_for_mission(Team $team, $m) { static $cache = [3=>[], 4=>[], 5=>[], 6=>[]]; if(array_key_exists($team->id, $cache[$m])) return $cache[$m][$team->id]; $num = Tweet::where('team_id', $team->id)->where('m'.$m.'_complete', 1)->count(); $cache[$m][$team->id] = $num; return $num; } public function complete(Team $team) { switch($this->id) { case 1: // 5 unique trimet transit lines return $this->unique_trimet_transit_lines($team) >= 5; case 2: // 3 unique transit centers return $this->unique_transit_centers($team) >= 3; case 3: case 4: case 5: case 6: return $this->num_tweets_for_mission($team, $this->id) >= 1; case 7: return $this->unique_documents($team) >= 3; } } public function progress(Team $team) { switch($this->id) { case 1: return [$this->unique_trimet_transit_lines($team), 5]; case 2: return [$this->unique_transit_centers($team), 3]; case 3: case 4: case 5: case 6: return [$this->num_tweets_for_mission($team, $this->id), 1]; case 7: return [$this->unique_documents($team), 3]; } return [false,false]; } public function score(Team $team) { switch($this->id) { case 1: // No points unless they hit 5 trimet transit lines if($this->complete($team)) { $score = 50; // 20 bonus for each line that is not trimet $tweets = Tweet::where('team_id', $team->id)->where('m1_complete', 1)->whereNotNull('m1_non_trimet')->get(); $lines = []; foreach($tweets as $tweet) { if(!in_array($tweet->m1_non_trimet, $lines)) { $lines[] = $tweet->m1_non_trimet; } } $score += count($lines) * 20; return $score; } else { return 0; } break; case 2: // No points unless they hit 3 transit centers if($this->complete($team)) { $score = 50; // If they have more than 3 unique transit centers, // then award bonus points for any beyond the third with another team $unique_transit_centers = $this->unique_transit_centers($team); if($unique_transit_centers > 3) { // Take the total number of transit centers and subtract 3 $total_possible_bonus = $unique_transit_centers - 3; // Find the number of unique transit centers with another team $unique_with_another_team = $this->unique_transit_centers($team, true); // Use the smaller of the two numbers as the bonus $score += 20 * min($total_possible_bonus, $unique_with_another_team); } // Increasing bonus points for additional transit centers if($unique_transit_centers >= 4) { $score += 10; } if($unique_transit_centers >= 5) { $score += 20; } if($unique_transit_centers >= 6) { $score += 30; } if($unique_transit_centers >= 7) { $score += (50 * ($unique_transit_centers - 6)); } // Triple points for each transit center that no other team goes to $this_team_tcs = Tweet::where('team_id', $team->id)->where('m2_complete', 1) ->distinct()->pluck('m2_transit_center_id')->toArray(); $other_visited_tcs = Tweet::where('team_id', '!=', $team->id)->where('m2_complete', 1) ->distinct()->pluck('m2_transit_center_id')->toArray(); $distinct_tcs = array_diff($this_team_tcs, $other_visited_tcs); Log::info('Team '.$team->name.' visited '.count($distinct_tcs).' TCs that no other team visited, doubling their score'); if(count($distinct_tcs) > 0) { $score *= 2; } return $score; } else { return 0; } break; case 3: case 4: case 6: if($this->complete($team)) { return 50; } else { return 0; } case 5: if($this->complete($team)) { $score = 50; return $score; } else { return 0; } case 7: if($this->complete($team)) { $score = 50; // +5 for each additional photo $extra_docs = $this->unique_documents($team) - 3; if($extra_docs > 0) { $score += $extra_docs * 5; } return $score; } else { return 0; } } } }