| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- <?php
- namespace App\Console\Commands;
- use Illuminate\Console\Command;
- use App\Models\Sport as SportModel;
- use App\Services\SportClientService;
- use Carbon\Carbon;
- use Illuminate\Support\Facades\DB;
- use App\Models\SportEvent;
- use App\Models\Config;
- class Sport extends Command
- {
- /**
- * 命令名称和签名
- *
- * @var string
- */
- protected $signature = 'sport {is_live=0}';
- protected $is_live = 0;
- protected $short_status = [
- 'TBD' => 0,
- 'NS' => 0,
- '1H' => 1,
- 'HT' => 1,
- '2H' => 1,
- 'ET' => 1,
- 'BT' => 1,
- 'P' => 1,
- 'SUSP' => 1,
- 'INT' => 1,
- 'FT' => 2,
- 'AET' => 2,
- 'PEN' => 2,
- 'PST' => 3,
- 'CANC' => 4,
- 'ABD' => 4,
- 'AWD' => 4,
- 'WO' => 4,
- 'LIVE' => 1,
- ];
- protected $long_status = [
- 'Time To Be Defined' => 0,
- 'Not Started' => 0,
- 'First Half' => 1,
- 'First Half, Kick Off' => 1,
- 'Halftime' => 1,
- 'Second Half' => 1,
- 'Second Half, 2nd Half Started' => 1,
- 'Extra Time' => 1,
- 'Break Time' => 1,
- 'Penalty In Progress' => 1,
- 'Match Suspended' => 1,
- 'Match Interrupted' => 1,
- 'Match Finished' => 2,
- 'Match Finished' => 2,
- 'Match Finished' => 2,
- 'Match Postponed' => 3,
- 'Match Cancelled' => 4,
- 'Match Abandoned' => 4,
- 'Technical Loss' => 4,
- 'WalkOver' => 4,
- 'In Progress' => 1,
- ];
-
- protected $fixture_status = [
- 'First Half' => 1,
- 'First Half, Kick Off' => 1,
- 'Halftime' => 1,
- 'Second Half' => 1,
- 'Second Half, 2nd Half Started' => 1,
- 'Extra Time' => 1,
- 'Break Time' => 1,
- 'Penalty In Progress' => 1,
- ];
-
- /**
- * 命令描述
- *
- * @var string
- */
- protected $description = '当天会去更新明天的赛事(23:59:00执行一次)';
- /**
- * 执行命令
- *
- * @return int
- */
- public function handle()
- {
- // $this->info('开始执行统计比赛数据任务...');
- $this->is_live = $this->argument('is_live');
- if ($this->is_live == 1) {
- //进行中的赛事,定时更新
- $this->liveFixtures();
- } elseif ($this->is_live == 0) {
- //未开始的赛事拉取
- $this->fixtures();
- } elseif ($this->is_live == 2){
- $this->checkLiveFixtures();
- //$this->updateOvertimeFixtures();
- } elseif ($this->is_live == 3) {
- $this->checkOvertimeFixtures();
- } else {
- $this->initOdds();
- }
- }
- //到了比赛开始时间,但是状态还是未开始,检查比赛
- public function checkOvertimeFixtures()
- {
- //体育赛事结束前几(分钟)锁盘,90分钟结束
- $sport_locked = Config::where('field', 'sport_locked')->first()->val ?? 1;
-
- // 比赛开始后,状态还是未开始的数据检测
- $ids = SportModel::where('status', 1)->where('state', 0)->where('game_time', '<=', time())->pluck('data_id')->toArray();
- if ($ids) {
- $ids = implode('-', $ids);
- $data = SportClientService::fixtures(['ids' => $ids]);
- $this->updateOrCreateSport($data, $sport_locked, 1);
- }
- return true;
- }
- //进行中超过3分钟没有更新数据的赛事,检查比赛是否结束
- public function checkLiveFixtures()
- {
- //体育赛事结束前几(分钟)锁盘,90分钟结束
- $sport_locked = Config::where('field', 'sport_locked')->first()->val ?? 1;
- //1. 统一锁盘时间(比赛开始前1分钟)
- SportModel::where(['is_locked' => 0, 'is_roll' => 0])->where('game_time', '<=', time() + 90)->update(['is_locked' => 1]);
- //2. 比赛进行中,超过3分钟未更新的数据检测
- $end_time = date("Y-m-d H:i:s", time() - 180);
- $ids = SportModel::where('status', 1)->where('state', 1)->where('updated_at', '<=', $end_time)->pluck('data_id')->toArray();
- if ($ids) {
- $chunks = array_chunk($ids, 10);
- foreach ($chunks as $chunk) {
- $ids = implode('-', $chunk);
- $data = SportClientService::fixtures(['ids' => $ids]);
- $this->updateOrCreateSport($data, $sport_locked, 1);
- }
- }
- return true;
- }
-
- //更新进行中的赛事
- public function liveFixtures()
- {
- //体育赛事结束前几(分钟)锁盘,90分钟结束
- $sport_locked = Config::where('field', 'sport_locked')->first()->val ?? 1;
- $data = SportClientService::fixtures(['live' => 'all']);
- file_put_contents("fixturesLive.json", json_encode($data));
- $this->updateOrCreateSport($data, $sport_locked);
- return true;
- }
- private function updateOrCreateSport($data, $sport_locked, $is_check = 0) {
- $data = $data['response'];
- $tableData = [];
- $status = $this->short_status;
- foreach ($data as $item) {
- $home_statistics = !empty($item['statistics']) ? $item['statistics'][0]['statistics'] : '';
- $away_statistics = !empty($item['statistics']) ? $item['statistics'][1]['statistics'] : '';
- $sport_data = [
- 'data_id' => $item['fixture']['id'],
- 'home_team_id' => $item['teams']['home']['id'],
- 'home_team_en' => $item['teams']['home']['name'],
- 'home_team' => lang($item['teams']['home']['name']),
- 'home_team_logo' => $item['teams']['home']['logo'],
- 'guest_team_id' => $item['teams']['away']['id'],
- 'guest_team_en' => $item['teams']['away']['name'],
- 'guest_team' => lang($item['teams']['away']['name']),
- 'guest_team_logo' => $item['teams']['away']['logo'],
- 'half_score' => "{$item['score']['halftime']['home']}-{$item['score']['halftime']['away']}",
- 'rbt' => $item['fixture']['timestamp'],
- 'score' => isset($item['goals']) ? "{$item['goals']['home']}-{$item['goals']['away']}":'-',
- 'extra_score' => isset($item['score']['extratime']) ? "{$item['score']['extratime']['home']}-{$item['score']['extratime']['away']}" : "",//加时赛比分
- 'league' => lang($item['league']['name']),
- 'league_en' => $item['league']['name'],
- 'state' => $status[$item['fixture']['status']['short']],//比赛状态:0未开始1进行中2已完场3延期4取消
- 'game_time' => $item['fixture']['timestamp'],
- 'updated_at' => now(),
- 'home_statistics' => $home_statistics,
- 'away_statistics' => $away_statistics,
- 'is_send' => 0,
- ];
-
-
- $info = SportModel::where('data_id', $item['fixture']['id'])->first();
-
- $fixture_status = null;
- if (empty($info->is_roll) && isset($item['fixture']['status']['long']) ) {
- $long = $item['fixture']['status']['long'];
- if (isset($this->fixture_status[$long])) {
- $fixture_status = json_encode($item['fixture']['status']);
- $sport_data['fixture_status'] = $fixture_status;
- }
- if (isset($this->long_status[$long])) {
- $sport_data['state'] = $this->long_status[$long];
- }
- }
- //提前锁盘(比赛进行时长,分钟)
- if (isset($item['fixture']['status']['elapsed'])) {
- $elapsed = $item['fixture']['status']['elapsed'];
- if ((int)$elapsed >= 90 - $sport_locked ) {
- $sport_data['is_locked'] = 1;
- }
- }
-
- $sport_data['score'] = $sport_data['score'] == '-' ? '' : $sport_data['score'];
- $sport_data['half_score'] = $sport_data['half_score'] == '-' ? '' : $sport_data['half_score'];
- $sport_data['extra_score'] = $sport_data['extra_score'] == '-' ? '' : $sport_data['extra_score'];
-
- //锁盘
- if (isset($item['fixture']['status']['blocked']) && $item['fixture']['status']['blocked']) {
- $sport_data['is_locked'] = 1;
- }
- //已结束
- if (isset($item['fixture']['status']['finished']) && $item['fixture']['status']['finished']) {
- $sport_data['state'] = 2;
- }
- //如果赛事取消、延期等,标记需要退款
- if ($sport_data['state'] > 2) {
- $sport_data['refund_status'] = 1;
- }
-
- if (!$info) {
- $sport_data['created_at'] = now();
- $sport_data['status'] = 1;
- $tableData[] = $sport_data;
- } else {
- SportModel::where('data_id', $item['fixture']['id'])->update($sport_data);
- }
- //比赛结束,插入比赛事件
- if ($sport_data['state'] == 2 && !empty($item['events'])) {
- foreach($item['events'] as $event) {
- SportEvent::create([
- 'data_id' => $item['fixture']['id'],
- 'type' => $event['type'],
- 'time_elapsed' => $event['time']['elapsed'],
- 'time' => json_encode($event['time']),
- 'detail' => $event['detail'],
- 'player' => $event['player'] ? json_encode($event['player']) : $event['player'],
- 'team_id' => $event['team']['id'],
- 'comments' => $event['comments'],
- 'assist' => $event['assist'] ? json_encode($event['assist']) : $event['assist'],
- ]);
- }
- }
- }
- if ($tableData) {
- SportModel::insert($tableData);
- }
- return true;
- }
-
- /**
- * 获取指定日期的所有赛事
- *
- * @return array
- */
- public function fixtures()
- {
- //根据配置拉取多少天的赛事信息
- $days = Config::where('field', 'sport_days')->first()->val ?? 1;
- for($i=0;$i<$days;$i++) {
- $date = Carbon::tomorrow()->addDay($i)->toDateString();
- $count = SportModel::where('game_time','>=', strtotime($date))->where('game_time','<=', strtotime($date." 23:59:59"))->count();
- if (!$count) {
- $data = SportClientService::fixtures(['date' => $date]);
-
- $data = $data['response'];
- $tableData = [];
- $status = $this->short_status;
- foreach ($data as $item) {
- $home_statistics = !empty($item['statistics']) ? $item['statistics'][0]['statistics'] : '';
- $away_statistics = !empty($item['statistics']) ? $item['statistics'][1]['statistics'] : '';
-
- $sport_data = [
- 'data_id' => $item['fixture']['id'],
- 'home_team_id' => $item['teams']['home']['id'],
- 'home_team_en' => $item['teams']['home']['name'],
- 'home_team' => lang($item['teams']['home']['name']),
- 'home_team_logo' => $item['teams']['home']['logo'],
- 'guest_team_id' => $item['teams']['away']['id'],
- 'guest_team_en' => $item['teams']['away']['name'],
- 'guest_team' => lang($item['teams']['away']['name']),
- 'guest_team_logo' => $item['teams']['away']['logo'],
- 'half_score' => "{$item['score']['halftime']['home']}-{$item['score']['halftime']['away']}",
- 'rbt' => $item['fixture']['timestamp'],
- 'score' => isset($item['score']['fulltime']) ? "{$item['score']['fulltime']['home']}-{$item['score']['fulltime']['away']}":'-',
- 'league' => lang($item['league']['name']),
- 'league_en' => $item['league']['name'],
- // 'state' => $status[$item['fixture']['status']['short']],//比赛状态:0未开始1进行中2已完场3延期4取消
- 'game_time' => $item['fixture']['timestamp'],
- 'status' => 1,
- 'updated_at' => now(),
- 'home_statistics' => $home_statistics,
- 'away_statistics' => $away_statistics,
- 'is_send' => 0,
- ];
- $status_short = strtoupper($item['fixture']['status']['short']);
- if (isset($status[$status_short])) {
- $sport_data['state'] = $status[$status_short];
- }
- $sport_data['score'] = $sport_data['score'] == '-' ? '' : $sport_data['score'];
- $sport_data['half_score'] = $sport_data['half_score'] == '-' ? '' : $sport_data['half_score'];
-
- if (!SportModel::where('data_id', $item['fixture']['id'])->exists()) {
- $sport_data['created_at'] = now();
- $tableData[] = $sport_data;
- } else {
- SportModel::where('data_id', $item['fixture']['id'])->update($sport_data);
- }
- //更新或创建球队和联赛信息
- SportModel::addSportTeam($sport_data);
- SportModel::addSportLeague($item['league']);
- //比赛结束,插入比赛事件
- if (isset($sport_data['state']) && $sport_data['state'] == 2 && !empty($item['events'])) {
- foreach($item['events'] as $event) {
- SportEvent::create([
- 'data_id' => $item['fixture']['id'],
- 'type' => $event['type'],
- 'time_elapsed' => $event['time']['elapsed'],
- 'time' => json_encode($event['time']),
- 'detail' => $event['detail'],
- 'player' => $event['player'] ? json_encode($event['player']) : $event['player'],
- 'team_id' => $event['team']['id'],
- 'comments' => $event['comments'],
- 'assist' => $event['assist'] ? json_encode($event['assist']) : $event['assist'],
- ]);
- }
-
- }
- }
- if ($tableData) {
- SportModel::insert($tableData);
- }
- }
- }
-
- return true;
- }
- public function initOdds(){
- $page = 1;
- $limit = 10;
- while (true) {
- $list = SportModel::where('odds','<>', null)->forPage($page, $limit)->get()->toArray();
- if (empty($list)) {
- break;
- }
- echo $page.PHP_EOL;
- foreach($list as $item) {
- $odds = json_decode($item['odds'], true);
- foreach($odds as $odd) {
- $odd_id = $odd['id'];
- $odd_name = $odd['name'];
- $info = DB::table('sport_odds')->where('odd_id',$odd_id)->where('odd_name_en',$odd_name)->first();
- if ($info && (!$info->odd_name || $odd_name != $info->odd_name_en)) {
- DB::table('sport_odds')->where('id', $info->id)->update([
- 'odd_name_en' => $odd_name,
- ]);
- } elseif (!$info) {
- DB::table('sport_odds')->insert([
- 'odd_id' => $odd_id,
- 'odd_name_en' => $odd_name,
- 'created_at' => date('Y-m-d H:i:s'),
- 'updated_at' => date('Y-m-d H:i:s'),
- ]);
- }
- }
- }
- $page++;
- }
- }
- //比赛开始后,超过3个小时,并且更新时间超过10分钟,还是进行中的数据,更新成已完成
- public function updateOvertimeFixtures()
- {
- // 比赛开始后,状态还是未开始的数据检测
- $end_time = date("Y-m-d H:i:s", time() - 600);
- SportModel::where('status', 1)->where('state', 1)->where('game_time', '<=', time() - 60*60*3)->where('updated_at', '<=', $end_time)->update(['state' =>2]);
- return true;
- }
- }
|