Skip to content

Commit da7b127

Browse files
committed
fix: fix score of timeline
1 parent 77320c2 commit da7b127

File tree

3 files changed

+50
-38
lines changed

3 files changed

+50
-38
lines changed

src/i18n/message/app/dashboard-resource.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@
6161
},
6262
"timeline": {
6363
"title": "Timeline of the recent {n} days",
64-
"busyScore": "Busy Score",
64+
"busyScore": "Busyness",
6565
"busyScoreDesc": "Related to the total browsing time and the number of websites per hour. See the source code for calculation formula",
66-
"focusScore": "Focus Score",
66+
"focusScore": "Focusness",
6767
"focusScoreDesc": "Related to the total time of continuous browsing of the same website. See the source code for calculation formula"
6868
}
6969
},

src/pages/app/components/Dashboard/components/Timeline/Chart/Wrapper.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,18 @@ const generateSeries = (biz: BizData, legendColors: Record<string, string>): EcO
144144
})
145145
}
146146

147+
const calcDataZoomDefaultRange = (activities: Activity[]): [start: number | undefined, end: number | undefined] => {
148+
if (!activities.length) return [undefined, undefined]
149+
let min = activities.map(a => a.start).reduce((a, b) => b < a ? b : a)
150+
let max = activities.map(({ start, duration }) => start + duration).reduce((a, b) => b > a ? b : a)
151+
152+
const interval = 30 * MILL_PER_MINUTE
153+
min = Math.floor(min / interval) * interval
154+
max = Math.ceil(max / interval) * interval
155+
156+
return [min, max]
157+
}
158+
147159
class Wrapper extends EchartsWrapper<BizData, EcOption> {
148160
protected replaceSeries: boolean = true
149161

@@ -163,6 +175,8 @@ class Wrapper extends EchartsWrapper<BizData, EcOption> {
163175
return name ? `${name} (${key})` : key
164176
}
165177

178+
const [zoomStart, zoomEnd] = calcDataZoomDefaultRange(bizData.activities)
179+
166180
return {
167181
grid: {
168182
left: gridLeft, width: domWidth - gridLeft - LEGEND_WIDTH,
@@ -175,6 +189,8 @@ class Wrapper extends EchartsWrapper<BizData, EcOption> {
175189
height: 20,
176190
labelFormatter: '',
177191
handleStyle: { opacity: 0 },
192+
startValue: zoomStart,
193+
endValue: zoomEnd,
178194
},
179195
yAxis: {
180196
type: 'category',

src/pages/app/components/Dashboard/components/Timeline/Summary.tsx

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,24 @@
11
import { t } from '@app/locale'
22
import { InfoFilled } from '@element-plus/icons-vue'
3+
import { useShadow } from '@hooks/index'
34
import Flex from '@pages/components/Flex'
45
import { groupBy } from '@util/array'
56
import { MILL_PER_HOUR, MILL_PER_MINUTE } from '@util/time'
67
import { ElIcon, ElRate, ElText, ElTooltip } from 'element-plus'
7-
import { computed, defineComponent, FunctionalComponent } from 'vue'
8-
9-
type ScoreValue = 1 | 2 | 3 | 4 | 5
8+
import { computed, defineComponent, watch } from 'vue'
109

1110
type AnalysisResult = {
12-
busy: ScoreValue
13-
focus: ScoreValue
11+
busy: number
12+
focus: number
1413
}
1514

15+
const MAX_SCORE = 5
16+
1617
const defaultResult = (): AnalysisResult => ({
1718
busy: 1,
1819
focus: 1,
1920
})
2021

21-
const cvtRaw2Score = (raw: number): ScoreValue => {
22-
if (raw < 1.5) return 1
23-
else if (raw < 2.5) return 2
24-
else if (raw < 3.5) return 3
25-
else if (raw < 4.5) return 4
26-
else return 5
27-
}
28-
2922
const computeSessionScore = (ticks: timer.timeline.Tick[], hourCount: number) => {
3023
let continuousSessions = 0
3124
let currentSession: timer.timeline.Tick[] = []
@@ -50,7 +43,7 @@ const computeSessionScore = (ticks: timer.timeline.Tick[], hourCount: number) =>
5043
if (currentSession.length > 1) continuousSessions++
5144

5245
const sessionDensity = continuousSessions / Math.max(1, hourCount / 10)
53-
return Math.min(sessionDensity, 1)
46+
return Math.min(sessionDensity, MAX_SCORE)
5447
}
5548

5649
const analyze = (ticks: timer.timeline.Tick[]): AnalysisResult => {
@@ -69,39 +62,42 @@ const analyze = (ticks: timer.timeline.Tick[]): AnalysisResult => {
6962

7063
// busyScore = timeDensity * 0.6 + hostCountPerHour * 0.4
7164
const timeDensity = totalActiveTime / totalRange
65+
const timeDensityScore = Math.min(timeDensity / 0.3, MAX_SCORE)
7266
const maxHostCount = Object.values(hourlyData).map(hosts => hosts.size).sort((a, b) => b - a)[0]!
73-
const busyRawScore = (timeDensity * 0.6 + (Math.min(maxHostCount / 10, 1) * 0.4)) * 5
67+
const hostMaxScore = Math.min(maxHostCount / 4, MAX_SCORE)
68+
const busy = timeDensityScore * 0.6 + hostMaxScore * 0.4
7469

7570
// focusScore = duration * 0.7 + session * 0.3
7671
const avgDuration = totalActiveTime / ticks.length
77-
const avgDurationScore = Math.min(avgDuration / (2 * MILL_PER_MINUTE), 1)
72+
const avgDurationScore = Math.min(avgDuration / (2 * MILL_PER_MINUTE), MAX_SCORE)
7873
const sessionScore = computeSessionScore(ticks, Object.keys(hourlyData).length)
79-
const focusRawScore = (avgDurationScore * 0.7 + sessionScore * 0.3) * 5
74+
const focus = avgDurationScore * 0.7 + sessionScore * 0.3
8075

81-
return {
82-
busy: cvtRaw2Score(busyRawScore),
83-
focus: cvtRaw2Score(focusRawScore),
84-
}
76+
return { busy, focus }
8577
}
8678

87-
const Score: FunctionalComponent<{ score: ScoreValue, label: string, desc: string }> = ({ score, label, desc }) => (
88-
<Flex align='center' column justify='center' gap={10}>
89-
<ElText>
90-
{`${label} `}
91-
<ElTooltip content={desc}>
92-
<ElText size='small'>
93-
<ElIcon>
94-
<InfoFilled />
95-
</ElIcon>
96-
</ElText>
97-
</ElTooltip>
98-
</ElText>
99-
<ElRate disabled modelValue={score} />
100-
</Flex>
101-
)
79+
const Score = defineComponent<{ score: number, label: string, desc: string }>(props => {
80+
const [score] = useShadow(() => props.score)
81+
return () => (
82+
<Flex align='center' column justify='center' gap={10}>
83+
<ElText>
84+
{`${props.label} `}
85+
<ElTooltip content={props.desc}>
86+
<ElText size='small'>
87+
<ElIcon>
88+
<InfoFilled />
89+
</ElIcon>
90+
</ElText>
91+
</ElTooltip>
92+
</ElText>
93+
<ElRate disabled modelValue={parseFloat(score.value.toFixed(1))} showScore />
94+
</Flex>
95+
)
96+
}, { props: ['desc', 'label', 'score'] })
10297

10398
const Summary = defineComponent<{ data: timer.timeline.Tick[] }>(props => {
10499
const ticks = computed(() => analyze(props.data))
100+
watch([ticks], () => console.log(ticks.value))
105101

106102
return () => (
107103
<Flex column justify='center' gap={30} height='100%'>

0 commit comments

Comments
 (0)