오픈 소스 모험: 에피소드 41: 러시아 손실 앱용 투영 기준 슬라이더
24903 단어 d3sveltejavascript
그러나 지금 당장은 대략 몇 달에 해당하는 약 3단계로 적합이 더 복잡해질 것으로 보입니다.
전선이 짧아지면 러시아군이 돈바스 포위 시도에 모든 부대를 투입하고 그곳에서 전투가 매우 치열할 것이라고 많은 사람들이 예상했지만 지금까지는 그렇지 않은 것 같습니다. 4월의 남부 전선은 3월의 남부 전선만큼 많은 전투가 발생하지만 북부 전선은 모두 사라졌기 때문에 전체 강도는 훨씬 낮습니다.
어쨌든 이것은 전체 데이터 세트에 선형 맞춤을 수행하는 대신 마지막 N일에만 선형 맞춤을 원한다는 것을 의미합니다. 여기서 해당 N은 다른 슬라이더로 제어됩니다. 초반이 가장 강렬했기 때문에 러시아가 마지막 탱크를 잃을 것으로 예상되는 시간이 지연될 것입니다.
슬라이더가 얼마나 멀리 갈 수 있습니까?
먼저
App.svelte
에서 데이터 로드를 수정하여 데이터가 얼마나 멀리 갈지 설정해야 합니다. 현재 53일(가능한 일수보다 1일 적음):import { dataDays } from "./stores"
let loadData = async () => {
let url = "./russia_losses_equipment.csv"
let data = await d3.csv(url, parseRow)
data.unshift({date: new Date("2022-02-24"), tank: 0, apc: 0, art: 0})
$dataDays = data.length - 1
return data
}
store.js
매장이 하나 더 필요합니다 -
dataDays
:import { writable, derived } from "svelte/store"
export let lossAdjustment = writable(0)
export let projectionBasis = writable(30)
export let futureIntensity = writable(100)
export let dataDays = writable(0)
export let activeTanks = writable(3417)
export let activeArmored = writable(18543)
export let activeArt = writable(5919)
export let storageTanks = writable(10200)
export let storageArmored = writable(15500)
export let storageGood = writable(10)
export let totalTanks = derived(
[activeTanks, storageTanks, storageGood],
([$activeTanks, $storageTanks, $storageGood]) => Math.round($activeTanks + $storageTanks * $storageGood / 100.0)
)
export let totalArmored = derived(
[activeArmored, storageArmored, storageGood],
([$activeArmored, $storageArmored, $storageGood]) => Math.round($activeArmored + $storageArmored * $storageGood / 100.0)
)
export let totalArt = activeArt
CommonSliders.svelte
이러한 양식 입력이 세 번 반복되므로 이를 공유 구성 요소로 추출했습니다.
<script>
import * as d3 from "d3"
import Slider from "./Slider.svelte"
import { lossAdjustment, projectionBasis, dataDays, futureIntensity } from "./stores"
</script>
<Slider label="Adjustment for losses data" min={-30} max={50} bind:value={$lossAdjustment} format={(v) => d3.format("+d")(v) + "%"} />
<Slider label="Projection basis in days" min={1} max={$dataDays} bind:value={$projectionBasis} format={(v) => `${v} days`} />
<Slider label="Predicted future war intensity" min={10} max={200} bind:value={$futureIntensity} format={(v) => `${v}%`} />
LossesGraph.svelte
이 파일에는
currentDestroyRate
에 대한 새로운 계산이 필요했습니다. 또한 Safari에는 여전히 at
가 없기 때문에 로컬Array.prototype.at
기능을 정의했으며 폴리필을 추가하는 것이 약간 번거롭습니다.<script>
import * as d3 from "d3"
import Graph from "./Graph.svelte"
import { lossAdjustment, projectionBasis, futureIntensity } from "./stores"
export let lossData, total, label
let adjust = (data, adjustmentLoss) => data.map(({date, unit}) => ({date, unit: Math.round(unit * (1 + adjustmentLoss/100))}))
let at = (array, idx) => ((idx < 0) ? array[array.length + idx] : array[idx])
let [minDate, maxDate] = d3.extent(lossData, d => d.date)
$: adjustedData = adjust(lossData, $lossAdjustment)
$: alreadyDestroyed = d3.max(adjustedData, d => d.unit)
$: unitsMax = Math.max(alreadyDestroyed, total)
$: timeInProjection = at(adjustedData, -$projectionBasis-1).date - at(adjustedData, -1).date
$: destroyedInProjection = at(adjustedData, -$projectionBasis-1).unit - at(adjustedData, -1).unit
$: currentDestroyRate = destroyedInProjection / timeInProjection
$: futureDestroyRate = (currentDestroyRate * $futureIntensity / 100.0)
$: unitsTodo = total - alreadyDestroyed
$: lastDestroyedDate = new Date(+maxDate + (unitsTodo / futureDestroyRate))
$: xScale = d3.scaleTime()
.domain([minDate, lastDestroyedDate])
.range([0, 700])
$: yScale = d3.scaleLinear()
.domain([0, unitsMax])
.nice()
.range([500, 0])
$: pathData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.unit))
(adjustedData)
$: trendPathData = d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.unit))
([adjustedData[0], at(adjustedData, -1), {unit: total, date: lastDestroyedDate}])
$: totalPathData = d3.line()
.x(xScale)
.y(yScale(unitsMax))
([minDate, lastDestroyedDate])
$: xAxis = d3.axisBottom()
.scale(xScale)
.tickFormat(d3.timeFormat("%e %b %Y"))
$: yAxisL = d3
.axisLeft()
.scale(yScale)
$: yScaleR = d3.scaleLinear()
.domain([0, 100])
.range([
yScale(0),
yScale(unitsMax)
])
$: yAxisR = d3
.axisRight()
.scale(yScaleR)
.tickFormat(n => `${n}%`)
</script>
<Graph {pathData} {trendPathData} {totalPathData} {xAxis} {yAxisL} {yAxisR} />
<div>Russia will lose its last {label} on {d3.timeFormat("%e %b %Y")(lastDestroyedDate)}</div>
지금까지의 이야기
All the code is on GitHub .
저는 이것을 GitHub Pagesyou can see it here에 배포했습니다.
다음에 온다
다음 에피소드에서는 개인 손실에 대한 예측을 추가하려고 합니다.
Reference
이 문제에 관하여(오픈 소스 모험: 에피소드 41: 러시아 손실 앱용 투영 기준 슬라이더), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/taw/open-source-adventures-episode-41-projection-basis-slider-for-russian-losses-app-3106텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)