오픈 소스 모험: 에피소드 51: 러시아 손실 앱 연마
29175 단어 javascriptsvelted3
나는 또한 더 많은 일을하고 싶습니다 :
그럼 시작하겠습니다!
바닥글.svelte
정적 HTML 일뿐입니다.
<footer>
Initial forces from <a href="https://www.iiss.org/publications/the-military-balance">IISS Military Balance 2022</a>.
Daily losses from <a href="https://www.kaggle.com/datasets/piterfm/2022-ukraine-russian-war">Ukraine Armed Forces.</a>
<a href="https://github.com/taw/open-source-adventures">Source code available on GitHub</a>.
</footer>
<style>
footer {
margin-top: 32px;
color: #444;
}
</style>
SoldierLossesGraph.svelte
이 구성 요소는 실제로 매우 복잡해지고 있으며 연말 총계에는 놀라운 반올림을 피하기 위해 상당히 복잡한 논리가 있습니다.
<script>
import * as d3 from "d3"
import SoldierGraph from "./SoldierGraph.svelte"
import { lossAdjustment, projectionBasis, wiaToKia, kiaRegular, futureIntensity } from "./stores"
export let lossData
let adjustRow = ({date, unit}, totalLossAdjustment, wiaToKia) => {
let kia = Math.round(unit * totalLossAdjustment)
let wia = Math.round(kia * wiaToKia / 100)
let total = kia + wia
return {date, kia, wia, total}
}
let adjust = (data, totalLossAdjustment, wiaToKia) => data.map(row => adjustRow(row, totalLossAdjustment, wiaToKia))
let at = (array, idx) => ((idx < 0) ? array[array.length + idx] : array[idx])
let round100 = (x) => Math.round(x / 100) * 100
let formatEoy = (x) => d3.format(".1f")(x / 1000.0) + "k"
let [minDate, maxDate] = d3.extent(lossData, d => d.date)
$: adjustedData = adjust(lossData, ($kiaRegular/100) * (1 + $lossAdjustment / 100.0), $wiaToKia)
$: totalSoFar = d3.max(adjustedData, d => d.total)
$: timeInProjection = at(adjustedData, -$projectionBasis-1).date - at(adjustedData, -1).date
$: kiaInProjection = at(adjustedData, -$projectionBasis-1).kia - at(adjustedData, -1).kia
$: wiaInProjection = at(adjustedData, -$projectionBasis-1).wia - at(adjustedData, -1).wia
$: currentKiaRate = kiaInProjection / timeInProjection
$: currentWiaRate = wiaInProjection / timeInProjection
$: futureKiaRate = (currentKiaRate * $futureIntensity / 100.0)
$: futureWiaRate = (currentWiaRate * $futureIntensity / 100.0)
$: futureTotalRate = futureKiaRate + futureWiaRate
// Just hardcode as there's no obvious "finish date"
$: lastDate = new Date("2023-01-01")
$: graphTime = lastDate - maxDate
// How many KIA+WIA by lastDate
$: unitsMax = Math.round(graphTime * futureTotalRate) + totalSoFar
$: kiaSoFar = d3.max(adjustedData, d => d.kia)
$: wiaSoFar = d3.max(adjustedData, d => d.wia)
$: eoyKia = round100(graphTime * futureKiaRate + kiaSoFar)
$: eoyWia = round100(graphTime * futureWiaRate + wiaSoFar)
$: eoyTotal = eoyKia + eoyWia
$: eoyIKia = round100(eoyKia / $kiaRegular * (100 - $kiaRegular))
$: eoyIWia = round100(eoyWia / $kiaRegular * (100 - $kiaRegular))
$: eoyITotal = eoyIKia + eoyIWia
$: trendData = [
adjustedData[0],
at(adjustedData, -1),
{
date: lastDate,
kia: Math.round(graphTime * futureKiaRate) + d3.max(adjustedData, d => d.kia),
wia: Math.round(graphTime * futureWiaRate) + d3.max(adjustedData, d => d.wia),
total: Math.round(graphTime * futureTotalRate) + d3.max(adjustedData, d => d.total),
},
]
$: xScale = d3.scaleTime()
.domain([minDate, lastDate])
.range([0, 700])
$: yScale = d3.scaleLinear()
.domain([0, unitsMax])
.nice()
.range([500, 0])
$: yAxis = d3
.axisLeft()
.scale(yScale)
$: xAxis = d3.axisBottom()
.scale(xScale)
.tickFormat(d3.timeFormat("%e %b %Y"))
$: kiaData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.kia))
(adjustedData)
$: wiaData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.wia))
(adjustedData)
$: totalData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.total))
(adjustedData)
$: kiaTrendData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.kia))
(trendData)
$: wiaTrendData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.wia))
(trendData)
$: totalTrendData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.total))
(trendData)
</script>
<SoldierGraph {xAxis} {yAxis} {kiaData} {wiaData} {totalData} {kiaTrendData} {wiaTrendData} {totalTrendData} />
<div>
<span class="box kia"></span> Killed
<span class="box wia"></span> Wounded
<span class="box total"></span> Total
</div>
<div>By end of the year, Russia will lose {formatEoy(eoyTotal)} ({formatEoy(eoyKia)} killed, {formatEoy(eoyWia)} wounded) regular soldiers.</div>
<div>As well as {formatEoy(eoyITotal)} ({formatEoy(eoyIKia)} killed, {formatEoy(eoyIWia)} wounded) irregulars (separatists, PMCs etc.)</div>
<style>
.box {
display: inline-block;
height: 10px;
width: 10px;
border: 1px solid black;
}
.box.kia {
background-color: red;
}
.box.wia {
background-color: green;
}
.box.total {
background-color: blue;
}
</style>
이렇게 하면 다음과 같은 요약이 생성됩니다.
By end of the year, Russia will lose 208.6k (59.6k killed, 149.0k wounded) regular soldiers.
As well as 52.2k (14.9k killed, 37.3k wounded) irregulars (separatists, PMCs etc.)
지금까지의 이야기
All the code is on GitHub .
저는 이것을 GitHub Pagesyou can see it here에 배포했습니다.
Reference
이 문제에 관하여(오픈 소스 모험: 에피소드 51: 러시아 손실 앱 연마), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/taw/open-source-adventures-episode-51-polishing-russian-losses-app-2a91텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)