Completed
Push — master ( cbe770...a806e4 )
by he
05:56
created

Team::totalPenalty()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 0
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Entities;
4
5
use Carbon\Carbon;
6
7
class Team
8
{
9
    protected $waCounts = [];
10
    /** @var Carbon[] */
11
    protected $timePassed = [];
12
13
    /** @var \App\Entities\User */
14
    protected $user;
15
16
    protected $accepts = 0;
17
    protected $submits = 0;
18
19
    /** @var Contest */
20
    protected $contest;
21
    private $problemCount;
22
23
    public function __construct(Contest $contest)
24
    {
25
        $this->contest = $contest;
26
27
        $this->problemCount = $contest->problems->count();
28
29
        for ($i = 0; $i < $this->problemCount; $i++) {
30
            $this->waCounts[$i] = 0;
31
            $this->timePassed[$i] = null;
32
        }
33
    }
34
35
    public function setUser(User $user)
36
    {
37
        $this->user = $user;
38
    }
39
40
    public function user(): User
41
    {
42
        return $this->user;
43
    }
44
45
    /**
46
     * 添加新的solution,统计数据.
47
     *
48
     * @param Solution $solution
49
     */
50
    public function addSolution(Solution $solution)
51
    {
52
        if ($this->problemCount === 0) {
53
            return;
54
        }
55
        $this->submits++;
56
57
        if ($solution->isAccepted()) {
58
            $this->markProblemAccept($solution);
59
        }
60
61
        if ($solution->isFailed()) {
62
            $this->addFailedCount($solution);
63
        }
64
    }
65
66
    private function addFailedCount(Solution $solution)
67
    {
68
        if (!array_key_exists($solution->order, $this->waCounts)) {
69
            $this->waCounts[$solution->order] = 0;
70
        }
71
72
        if ($this->shouldMarkAsPenalty($solution)) {
73
            $this->waCounts[$solution->order]++;
74
        }
75
    }
76
77
    private function shouldMarkAsPenalty(Solution $solution): bool
78
    {
79
        if ($this->timePassed[$solution->order]
80
            && $this->timePassed[$solution->order]->gt($solution->created_at)) {
81
            return false;
82
        }
83
84
        return true;
85
    }
86
87
    /**
88
     * 获取通过的题目数.
89
     *
90
     * @return int
91
     */
92
    public function numberOfAccept()
93
    {
94
        return $this->accepts;
95
    }
96
97
    public function getNumberOfSubmit()
98
    {
99
        return $this->submits;
100
    }
101
102
    /**
103
     * 获取题目的尝试次数.
104
     *
105
     * @param $pid
106
     *
107
     * @return mixed
108
     */
109
    public function getProblemWACount($pid)
110
    {
111
        return $this->waCounts[$pid];
112
    }
113
114
    public function getProblemAcceptTime($pid)
115
    {
116
        if (null === $this->timePassed[$pid]) {
117
            return 0;
118
        }
119
120
        $start = new Carbon($this->contest->start_time);
121
122
        return $this->timePassed[$pid]->diffInSeconds($start);
123
    }
124
125
    public function isProblemAccept($pid)
126
    {
127
        return null !== $this->timePassed[$pid];
128
    }
129
130
    /**
131
     * 获取总时间.
132
     *
133
     * @return int|mixed
134
     */
135
    public function totalPenalty()
136
    {
137
        $totalTime = 0;
138
        $number_of_problem = $this->contest->problems->count();
139
        for ($i = 0; $i < $number_of_problem; $i++) {
140
            $accepted_at = $this->getProblemAcceptTime($i);
141
            if ($accepted_at > 0) {
142
                // 只有通过的题目才需要计算时间和罚时
143
                $totalTime += $accepted_at;
144
                $totalTime += $this->getPenaltyOfProblem($i);
145
            }
146
        }
147
148
        return $totalTime;
149
    }
150
151
    /**
152
     * 获取单个题目的罚时.
153
     *
154
     * @param $pid
155
     *
156
     * @return mixed
157
     */
158
    public function getPenaltyOfProblem($pid)
159
    {
160
        return $this->getProblemWACount($pid) * 20 * 60;
161
    }
162
163
    /**
164
     * @param Solution $solution
165
     */
166
    private function markProblemAccept($solution)
167
    {
168
        $pid = $solution->order;
169
        if (!array_key_exists($pid, $this->timePassed) || $this->timePassed[$pid] === null) {
170
            $this->timePassed[$pid] = $solution->created_at;
171
            $this->accepts++;
172
        } else {
173
            if ($this->timePassed[$pid]->gt($solution->created_at)) {
174
                $this->timePassed[$pid] = $solution->created_at;
175
            }
176
        }
177
    }
178
}
179