Skip to content

Commit

Permalink
✨ レインボーラインのデータの可視化を追加
Browse files Browse the repository at this point in the history
  • Loading branch information
yamaji committed Nov 14, 2024
1 parent fb6d592 commit 9309429
Show file tree
Hide file tree
Showing 7 changed files with 381 additions and 1 deletion.
16 changes: 16 additions & 0 deletions app/[year]/[month]/[date]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import DateNavigation from "@/components/date-navigation.component";
import DetectedFaceGraph from "@/components/graphs/detected-face.component";
import DetectedLisencePlateGraph from "@/components/graphs/detected-license-plate.component";
import DetectedPeopleGraph from "@/components/graphs/detected-people.component";
import EstimatedAgeGraph from "@/components/graphs/estimated-age.component";
import EstimatedGenderGraph from "@/components/graphs/estimated-gender.component";
import EstimatedPrefectureGraph from "@/components/graphs/estimated-prefecture.component";
import EstimatedRentalCarGraph from "@/components/graphs/estimated-rental-car.component";
import { DateService } from "@/services/date.service";

export async function generateStaticParams() {
Expand Down Expand Up @@ -52,6 +55,19 @@ export default async function page({
<EstimatedGenderGraph place={"tojinbo"} date={date} />
</div>
</article>
<article className="mb-4 flex flex-col items-center p-4">
<h2 className="mb-2 text-xl font-bold">
レインボーライン第一駐車場入口でのAIカメラによる解析
</h2>
<div className="grid h-full w-full grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
<DetectedFaceGraph place={"rainbow-one"} date={date} />
<EstimatedAgeGraph place={"rainbow-one"} date={date} />
<EstimatedGenderGraph place={"rainbow-one"} date={date} />
<DetectedLisencePlateGraph place={"rainbow-one"} date={date} />
<EstimatedPrefectureGraph place={"rainbow-one"} date={date} />
<EstimatedRentalCarGraph place={"rainbow-one"} date={date} />
</div>
</article>
</>
);
}
16 changes: 16 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import DateNavigation from "@/components/date-navigation.component";
import DetectedFaceGraph from "@/components/graphs/detected-face.component";
import DetectedLisencePlateGraph from "@/components/graphs/detected-license-plate.component";
import DetectedPeopleGraph from "@/components/graphs/detected-people.component";
import EstimatedAgeGraph from "@/components/graphs/estimated-age.component";
import EstimatedGenderGraph from "@/components/graphs/estimated-gender.component";
import EstimatedPrefectureGraph from "@/components/graphs/estimated-prefecture.component";
import EstimatedRentalCarGraph from "@/components/graphs/estimated-rental-car.component";

export default async function Home() {
const date = new Date();
Expand All @@ -28,6 +31,19 @@ export default async function Home() {
<EstimatedGenderGraph place={"tojinbo"} date={date} />
</div>
</article>
<article className="mb-4 flex flex-col items-center p-4">
<h2 className="mb-2 text-xl font-bold">
レインボーライン第一駐車場入口でのAIカメラによる解析
</h2>
<div className="grid h-full w-full grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
<DetectedFaceGraph place={"rainbow-one"} date={date} />
<EstimatedAgeGraph place={"rainbow-one"} date={date} />
<EstimatedGenderGraph place={"rainbow-one"} date={date} />
<DetectedLisencePlateGraph place={"rainbow-one"} date={date} />
<EstimatedPrefectureGraph place={"rainbow-one"} date={date} />
<EstimatedRentalCarGraph place={"rainbow-one"} date={date} />
</div>
</article>
</>
);
}
39 changes: 39 additions & 0 deletions components/graphs/detected-license-plate.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Place } from "@/interfaces/place.interface";
import { DataService } from "@/services/data.service";
import Card from "../card.component";
import { Graph } from "../graph.component";

export default async function DetectedLisencePlateGraph(props: { place: Place; date: Date }) {
const dataService = new DataService();

const year = props.date.getFullYear();
const month = props.date.getMonth() + 1;
const day = props.date.getDate();

const data = (await dataService.get(props.place, year, month, day)).filter(
(row) => row[1] === "LicensePlate",
);

const licensePlateAt: number[] = (() => {
const arr = [];
for (let _ = 0; _ < 24; _++) arr.push(0);
return arr;
})();
data.forEach((row) => (licensePlateAt[new Date(row[2]).getHours()] += 1));
const options = {
series: [
{
type: "column",
data: licensePlateAt.map((v, i) => ({ x: `${i}時`, y: `${v}回` })),
},
],
labels: licensePlateAt.map((_, i) => (i % 3 === 0 ? `${i}時` : "")),
};

return (
<Card title="単位時間あたりにナンバープレートが検出された回数">
<p className="text-sm">{`合計: ${licensePlateAt.reduce((sum, v) => sum + v, 0)}回`}</p>
<Graph type="bar" series={options.series} options={options} />
</Card>
);
}
50 changes: 50 additions & 0 deletions components/graphs/estimated-prefecture.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Place } from "@/interfaces/place.interface";
import { DataService } from "@/services/data.service";
import Card from "../card.component";
import { Graph } from "../graph.component";
import { aRegionFromRegion } from "@/interfaces/license-plate.interface";

export default async function EstimatedPrefectureGraph(props: { place: Place; date: Date }) {
const dataService = new DataService();

const year = props.date.getFullYear();
const month = props.date.getMonth() + 1;
const day = props.date.getDate();

const data = (await dataService.get(props.place, year, month, day))
.filter((row) => row[1] === "LicensePlate")
.map((row) => aRegionFromRegion(row[7]))
.filter((row) => typeof row !== "undefined")
.reduce(
(p: { answer: string; count: number }[][], c) => {
if (!p[0].map((v) => v.answer).includes(c)) p[0].push({ answer: c, count: 0 });
p[0][p[0].map((v) => v.answer).indexOf(c)].count += 1;
return p;
},
[[]],
)[0]
.sort((a, b) => b.count - a.count);

const options = {
series: data.map((v) => v.count),
labels: data.map((v) => v.answer),
plotOptions: {
pie: {
donut: {
labels: {
show: true,
total: {
show: true,
},
},
},
},
},
};

return (
<Card title="認識されたナンバープレートの地域の割合">
<Graph type="donut" series={options.series} options={options} />
</Card>
);
}
48 changes: 48 additions & 0 deletions components/graphs/estimated-rental-car.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Place } from "@/interfaces/place.interface";
import { DataService } from "@/services/data.service";
import Card from "../card.component";
import { Graph } from "../graph.component";

export default async function EstimatedRentalCarGraph(props: { place: Place; date: Date }) {
const dataService = new DataService();

const year = props.date.getFullYear();
const month = props.date.getMonth() + 1;
const day = props.date.getDate();

const data = (await dataService.get(props.place, year, month, day))
.filter((row) => row[1] === "LicensePlate")
.map((row) => (["れ", "わ"].includes(row[9]) ? "レンタカー" : "その他"))
.reduce(
(p: { answer: string; count: number }[][], c) => {
if (!p[0].map((v) => v.answer).includes(c)) p[0].push({ answer: c, count: 0 });
p[0][p[0].map((v) => v.answer).indexOf(c)].count += 1;
return p;
},
[[]],
)[0]
.sort((a, b) => (a.answer === "レンタカー" ? 0 : 1) - (b.answer === "レンタカー" ? 0 : 1));

const options = {
series: data.map((v) => v.count),
labels: data.map((v) => v.answer),
plotOptions: {
pie: {
donut: {
labels: {
show: true,
total: {
show: true,
},
},
},
},
},
};

return (
<Card title="レンタカーと推測された車の割合">
<Graph type="donut" series={options.series} options={options} />
</Card>
);
}
Loading

0 comments on commit 9309429

Please sign in to comment.