Skip to content

Commit

Permalink
Add pileg_dpr_dapil
Browse files Browse the repository at this point in the history
  • Loading branch information
ronnygunawan committed Feb 17, 2024
1 parent a3c7f17 commit a31117c
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 15 deletions.
3 changes: 2 additions & 1 deletion BotNet.CommandHandlers/SQL/SQLCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ await _telegramBotClient.SendTextMessageAsync(
chatId: command.Chat.Id,
text: $$"""
<code>Table '{{table}}' not found. Available tables are:
- pileg_dpr
- pileg_dpr_dapil
- pileg_dpr_provinsi
- pilpres
- vps
</code>
Expand Down
158 changes: 158 additions & 0 deletions BotNet.Services/Pemilu2024/PilegDPRPerDapilDataSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BotNet.Services.SQL;
using BotNet.Services.Sqlite;

namespace BotNet.Services.Pemilu2024 {
public sealed class PilegDPRPerDapilDataSource(
ScopedDatabase scopedDatabase,
SirekapClient sirekapClient
) : IScopedDataSource {
private const string PKB = "1";
private const string GERINDRA = "2";
private const string PDIP = "3";
private const string GOLKAR = "4";
private const string NASDEM = "5";
private const string PARTAI_BURUH = "6";
private const string GELORA = "7";
private const string PKS = "8";
private const string PKN = "9";
private const string HANURA = "10";
private const string GARUDA = "11";
private const string PAN = "12";
private const string PBB = "13";
private const string DEMOKRAT = "14";
private const string PSI = "15";
private const string PERINDO = "16";
private const string PPP = "17";
private const string PNA = "18";
private const string GABTHAT = "19";
private const string PDA = "20";
private const string PARTAI_ACEH = "21";
private const string PAS_ACEH = "22";
private const string PARTAI_SIRA = "23";
private const string PARTAI_UMMAT = "24";
private readonly ScopedDatabase _scopedDatabase = scopedDatabase;
private readonly SirekapClient _sirekapClient = sirekapClient;

public async Task LoadTableAsync(CancellationToken cancellationToken) {
_scopedDatabase.ExecuteNonQuery("""
CREATE TABLE pileg_dpr_dapil (
kode_dapil VARCHAR(5) PRIMARY KEY,
dapil VARCHAR(50),
progress REAL,
pkb INTEGER,
gerindra INTEGER,
pdip INTEGER,
golkar INTEGER,
nasdem INTEGER,
partai_buruh INTEGER,
gelora INTEGER,
pks INTEGER,
pkn INTEGER,
hanura INTEGER,
garuda INTEGER,
pan INTEGER,
pbb INTEGER,
demokrat INTEGER,
psi INTEGER,
perindo INTEGER,
ppp INTEGER,
pna INTEGER,
gabthat INTEGER,
pda INTEGER,
partai_aceh INTEGER,
pas_aceh INTEGER,
partai_sira INTEGER,
partai_ummat INTEGER,
total INTEGER
)
""");

IList<Wilayah> listDapilDPR = await _sirekapClient.GetDapilDPRListAsync(cancellationToken);
Dictionary<string, Wilayah> dapilByKode = listDapilDPR.ToDictionary(
keySelector: dapil => dapil.Kode
);

ReportPilegDPRByDapil report = await _sirekapClient.GetReportPilegDPRByDapilAsync(cancellationToken);

foreach ((string kodeDapil, ReportPilegDPRByDapil.Row? row) in report.RowByKodeDapil.OrderBy(pair => pair.Key)) {
if (row == null) {
_scopedDatabase.ExecuteNonQuery("""
INSERT INTO pileg_dpr_dapil (kode_dapil, dapil, progress, pkb, gerindra, pdip, golkar, nasdem, partai_buruh, gelora, pks, pkn, hanura, garuda, pan, pbb, demokrat, psi, perindo, ppp, pna, gabthat, pda, partai_aceh, pas_aceh, partai_sira, partai_ummat, total)
VALUES (@kode_dapil, @dapil, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)
""",
[
( "@kode_dapil", kodeDapil ),
( "@dapil", dapilByKode[kodeDapil].Nama )
]
);
continue;
}

int? pkb = row.VotesByKodePartai!.TryGetValue(PKB, out int p) ? p : null;
int? gerindra = row.VotesByKodePartai!.TryGetValue(GERINDRA, out int g) ? g : null;
int? pdip = row.VotesByKodePartai!.TryGetValue(PDIP, out int pd) ? pd : null;
int? golkar = row.VotesByKodePartai!.TryGetValue(GOLKAR, out int go) ? go : null;
int? nasdem = row.VotesByKodePartai!.TryGetValue(NASDEM, out int n) ? n : null;
int? partai_buruh = row.VotesByKodePartai!.TryGetValue(PARTAI_BURUH, out int pb) ? pb : null;
int? gelora = row.VotesByKodePartai!.TryGetValue(GELORA, out int ge) ? ge : null;
int? pks = row.VotesByKodePartai!.TryGetValue(PKS, out int pk) ? pk : null;
int? pkn = row.VotesByKodePartai!.TryGetValue(PKN, out int pn) ? pn : null;
int? hanura = row.VotesByKodePartai!.TryGetValue(HANURA, out int h) ? h : null;
int? garuda = row.VotesByKodePartai!.TryGetValue(GARUDA, out int ga) ? ga : null;
int? pan = row.VotesByKodePartai!.TryGetValue(PAN, out int pa) ? pa : null;
int? pbb = row.VotesByKodePartai!.TryGetValue(PBB, out int pb2) ? pb2 : null;
int? demokrat = row.VotesByKodePartai!.TryGetValue(DEMOKRAT, out int d) ? d : null;
int? psi = row.VotesByKodePartai!.TryGetValue(PSI, out int ps) ? ps : null;
int? perindo = row.VotesByKodePartai!.TryGetValue(PERINDO, out int pe) ? pe : null;
int? ppp = row.VotesByKodePartai!.TryGetValue(PPP, out int pp) ? pp : null;
int? pna = row.VotesByKodePartai!.TryGetValue(PNA, out int pn2) ? pn2 : null;
int? gabthat = row.VotesByKodePartai!.TryGetValue(GABTHAT, out int gab) ? gab : null;
int? pda = row.VotesByKodePartai!.TryGetValue(PDA, out int pd2) ? pd2 : null;
int? partai_aceh = row.VotesByKodePartai!.TryGetValue(PARTAI_ACEH, out int pa2) ? pa2 : null;
int? pas_aceh = row.VotesByKodePartai!.TryGetValue(PAS_ACEH, out int pas) ? pas : null;
int? partai_sira = row.VotesByKodePartai!.TryGetValue(PARTAI_SIRA, out int s) ? s : null;
int? partai_ummat = row.VotesByKodePartai!.TryGetValue(PARTAI_UMMAT, out int u) ? u : null;
int total = (pkb ?? 0) + (gerindra ?? 0) + (pdip ?? 0) + (golkar ?? 0) + (nasdem ?? 0) + (partai_buruh ?? 0) + (gelora ?? 0) + (pks ?? 0) + (pkn ?? 0) + (hanura ?? 0) + (garuda ?? 0) + (pan ?? 0) + (pbb ?? 0) + (demokrat ?? 0) + (psi ?? 0) + (perindo ?? 0) + (ppp ?? 0) + (pna ?? 0) + (gabthat ?? 0) + (pda ?? 0) + (partai_aceh ?? 0) + (pas_aceh ?? 0) + (partai_sira ?? 0) + (partai_ummat ?? 0);
_scopedDatabase.ExecuteNonQuery("""
INSERT INTO pileg_dpr_dapil (kode_dapil, dapil, progress, pkb, gerindra, pdip, golkar, nasdem, partai_buruh, gelora, pks, pkn, hanura, garuda, pan, pbb, demokrat, psi, perindo, ppp, pna, gabthat, pda, partai_aceh, pas_aceh, partai_sira, partai_ummat, total)
VALUES (@kode_dapil, @dapil, @progress, @pkb, @gerindra, @pdip, @golkar, @nasdem, @partai_buruh, @gelora, @pks, @pkn, @hanura, @garuda, @pan, @pbb, @demokrat, @psi, @perindo, @ppp, @pna, @gabthat, @pda, @partai_aceh, @pas_aceh, @partai_sira, @partai_ummat, @total)
""",
[
( "@kode_dapil", kodeDapil ),
( "@dapil", dapilByKode[kodeDapil].Nama ),
( "@progress", row.Persen ),
( "@pkb", pkb),
( "@gerindra", gerindra),
( "@pdip", pdip),
( "@golkar", golkar),
( "@nasdem", nasdem),
( "@partai_buruh", partai_buruh),
( "@gelora", gelora),
( "@pks", pks),
( "@pkn", pkn),
( "@hanura", hanura),
( "@garuda", garuda),
( "@pan", pan),
( "@pbb", pbb),
( "@demokrat", demokrat),
( "@psi", psi),
( "@perindo", perindo),
( "@ppp", ppp),
( "@pna", pna),
( "@gabthat", gabthat),
( "@pda", pda),
( "@partai_aceh", partai_aceh),
( "@pas_aceh", pas_aceh),
( "@partai_sira", partai_sira),
( "@partai_ummat", partai_ummat),
( "@total", total)
]
);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using BotNet.Services.Sqlite;

namespace BotNet.Services.Pemilu2024 {
public sealed class PilegDPRDataSource(
public sealed class PilegDPRPerProvinsiDataSource(
ScopedDatabase scopedDatabase,
SirekapClient sirekapClient
) : IScopedDataSource {
Expand Down Expand Up @@ -39,7 +39,7 @@ SirekapClient sirekapClient

public async Task LoadTableAsync(CancellationToken cancellationToken) {
_scopedDatabase.ExecuteNonQuery("""
CREATE TABLE pileg_dpr (
CREATE TABLE pileg_dpr_provinsi (
provinsi VARCHAR(50) PRIMARY KEY,
progress REAL,
pkb INTEGER,
Expand Down Expand Up @@ -75,9 +75,9 @@ total INTEGER
keySelector: provinsi => provinsi.Kode
);

ReportPilegDPR report = await _sirekapClient.GetReportPilegDPRAsync(cancellationToken);
ReportPilegDPRByWilayah report = await _sirekapClient.GetReportPilegDPRByProvinsiAsync(cancellationToken);

foreach ((string kodeWilayah, ReportPilegDPR.Row row) in report.RowByKodeWilayah.OrderBy(pair => pair.Key)) {
foreach ((string kodeWilayah, ReportPilegDPRByWilayah.Row row) in report.RowByKodeWilayah.OrderBy(pair => pair.Key)) {
int? pkb = row.VotesByKodePartai!.TryGetValue(PKB, out int p) ? p : null;
int? gerindra = row.VotesByKodePartai!.TryGetValue(GERINDRA, out int g) ? g : null;
int? pdip = row.VotesByKodePartai!.TryGetValue(PDIP, out int pd) ? pd : null;
Expand All @@ -104,7 +104,7 @@ total INTEGER
int? partai_ummat = row.VotesByKodePartai!.TryGetValue(PARTAI_UMMAT, out int u) ? u: null;
int total = (pkb ?? 0) + (gerindra ?? 0) + (pdip ?? 0) + (golkar ?? 0) + (nasdem ?? 0) + (partai_buruh ?? 0) + (gelora ?? 0) + (pks ?? 0) + (pkn ?? 0) + (hanura ?? 0) + (garuda ?? 0) + (pan ?? 0) + (pbb ?? 0) + (demokrat ?? 0) + (psi ?? 0) + (perindo ?? 0) + (ppp ?? 0) + (pna ?? 0) + (gabthat ?? 0) + (pda ?? 0) + (partai_aceh ?? 0) + (pas_aceh ?? 0) + (partai_sira ?? 0) + (partai_ummat ?? 0);
_scopedDatabase.ExecuteNonQuery("""
INSERT INTO pileg_dpr (provinsi, progress, pkb, gerindra, pdip, golkar, nasdem, partai_buruh, gelora, pks, pkn, hanura, garuda, pan, pbb, demokrat, psi, perindo, ppp, pna, gabthat, pda, partai_aceh, pas_aceh, partai_sira, partai_ummat, total)
INSERT INTO pileg_dpr_provinsi (provinsi, progress, pkb, gerindra, pdip, golkar, nasdem, partai_buruh, gelora, pks, pkn, hanura, garuda, pan, pbb, demokrat, psi, perindo, ppp, pna, gabthat, pda, partai_aceh, pas_aceh, partai_sira, partai_ummat, total)
VALUES (@provinsi, @progress, @pkb, @gerindra, @pdip, @golkar, @nasdem, @partai_buruh, @gelora, @pks, @pkn, @hanura, @garuda, @pan, @pbb, @demokrat, @psi, @perindo, @ppp, @pna, @gabthat, @pda, @partai_aceh, @pas_aceh, @partai_sira, @partai_ummat, @total)
""",
[
Expand Down
3 changes: 2 additions & 1 deletion BotNet.Services/Pemilu2024/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ public static class ServiceCollectionExtensions {
public static IServiceCollection AddPemilu2024(this IServiceCollection services) {
services.AddTransient<SirekapClient>();
services.AddKeyedTransient<IScopedDataSource, PilpresDataSource>("pilpres");
services.AddKeyedTransient<IScopedDataSource, PilegDPRDataSource>("pileg_dpr");
services.AddKeyedTransient<IScopedDataSource, PilegDPRPerProvinsiDataSource>("pileg_dpr_provinsi");
services.AddKeyedTransient<IScopedDataSource, PilegDPRPerDapilDataSource>("pileg_dpr_dapil");
return services;
}
}
Expand Down
11 changes: 9 additions & 2 deletions BotNet.Services/Pemilu2024/SirekapClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,18 @@ public async Task<ReportPilpres> GetReportPilpresByWilayahAsync(string kodeWilay
) ?? throw new JsonException("Unexpected response");
}

public async Task<ReportPilegDPR> GetReportPilegDPRAsync(CancellationToken cancellationToken) {
return await _httpClient.GetFromJsonAsync<ReportPilegDPR>(
public async Task<ReportPilegDPRByWilayah> GetReportPilegDPRByProvinsiAsync(CancellationToken cancellationToken) {
return await _httpClient.GetFromJsonAsync<ReportPilegDPRByWilayah>(
requestUri: "https://sirekap-obj-data.kpu.go.id/pemilu/hhcw/pdpr.json",
cancellationToken: cancellationToken
) ?? throw new JsonException("Unexpected response");
}

public async Task<ReportPilegDPRByDapil> GetReportPilegDPRByDapilAsync(CancellationToken cancellationToken) {
return await _httpClient.GetFromJsonAsync<ReportPilegDPRByDapil>(
requestUri: "https://sirekap-obj-data.kpu.go.id/pemilu/hhcd/pdpr/0.json",
cancellationToken: cancellationToken
) ?? throw new JsonException("Unexpected response");
}
}
}
50 changes: 44 additions & 6 deletions BotNet.Services/Pemilu2024/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ int Progres
);
}

public sealed record ReportPilegDPR(
public sealed record ReportPilegDPRByWilayah(
[property: JsonPropertyName("ts")] string Timestamp,
string Psu,
string Mode,
IDictionary<string, decimal> Chart,
[property: JsonPropertyName("table")] IDictionary<string, ReportPilegDPR.Row> RowByKodeWilayah,
ReportPilegDPR.Progress Progres
[property: JsonPropertyName("table")] IDictionary<string, ReportPilegDPRByWilayah.Row> RowByKodeWilayah,
ReportPilegDPRByWilayah.Progress Progres
) {
public sealed record Row {
public string? Psu { get; set; }
Expand All @@ -91,14 +91,52 @@ public IDictionary<string, int>? VotesByKodePartai {
return null;
}

Dictionary<string, int> votesByKodeCalon = [];
Dictionary<string, int> votesByKodePartai = [];
foreach (KeyValuePair<string, JsonElement> kvp in VotesByKodePartaiJson) {
if (kvp.Value.ValueKind == JsonValueKind.Number
&& kvp.Value.TryGetInt32(out int votes)) {
votesByKodeCalon[kvp.Key] = votes;
votesByKodePartai[kvp.Key] = votes;
}
}
return votesByKodeCalon;
return votesByKodePartai;
}
}
}

public sealed record Progress(
int Total,
int Progres
);
}

public sealed record ReportPilegDPRByDapil(
[property: JsonPropertyName("ts")] string Timestamp,
string Mode,
IDictionary<string, decimal> Chart,
[property: JsonPropertyName("table")] IDictionary<string, ReportPilegDPRByDapil.Row?> RowByKodeDapil,
ReportPilegDPRByDapil.Progress Progres
) {
public sealed record Row {
public decimal Persen { get; set; }

[JsonExtensionData]
public IDictionary<string, JsonElement>? VotesByKodePartaiJson { get; set; }

[JsonIgnore]
public IDictionary<string, int>? VotesByKodePartai {
get {
if (VotesByKodePartaiJson is null) {
return null;
}

Dictionary<string, int> votesByKodePartai = [];
foreach (KeyValuePair<string, JsonElement> kvp in VotesByKodePartaiJson) {
if (kvp.Value.ValueKind == JsonValueKind.Number
&& kvp.Value.TryGetInt32(out int votes)) {
votesByKodePartai[kvp.Key] = votes;
}
}
return votesByKodePartai;
}
}
}
Expand Down

0 comments on commit a31117c

Please sign in to comment.