Compare commits
47 Commits
e56fc253ba
...
council_20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fde39bcb1b | ||
| 5791273f56 | |||
|
|
45a5afc5f9 | ||
|
|
7af17f0e0b | ||
|
|
c9ec1933f6 | ||
|
|
f8fd1cc20c | ||
|
|
464d617ecc | ||
|
|
af457dbd8c | ||
|
|
dea1ccfe86 | ||
|
|
abf5147c79 | ||
|
|
6eef04e89f | ||
|
|
bac9be7003 | ||
| 910bfe85c1 | |||
|
|
b8a29a1de2 | ||
|
|
c47eb353a7 | ||
|
|
51af861f38 | ||
|
|
74c24a37a2 | ||
|
|
802c091ba2 | ||
|
|
ccae561fda | ||
|
|
34e0297947 | ||
|
|
abb4f5675c | ||
|
|
3708a694ed | ||
|
|
9f25e4039e | ||
|
|
84e7d472a9 | ||
|
|
73e4ed85d0 | ||
|
|
decc12f381 | ||
|
|
8543bc1c53 | ||
|
|
620d1bf06d | ||
|
|
1f5dc18e81 | ||
| 94ea4f6a5f | |||
|
|
72eba5fd58 | ||
|
|
68938751d4 | ||
|
|
8b2e66b044 | ||
|
|
db2d4fcbc7 | ||
|
|
d8591d5625 | ||
|
|
a30855ac30 | ||
|
|
6df6cc2d5e | ||
| 03652e1285 | |||
|
|
c27cc2831b | ||
| fff24136a1 | |||
| 45eba00d5d | |||
| 0f05fe20ec | |||
|
|
f9c151bfae | ||
|
|
219b242503 | ||
|
|
2f5806a227 | ||
|
|
e2fbd1b1ef | ||
|
|
2453d550ce |
@@ -35,7 +35,7 @@ The "short" named is created by taking the electorate name and removing the word
|
||||
The file can be generated using the `jq` tool and the VEC data:
|
||||
|
||||
```
|
||||
jq '[.[] | {name: .electorateName, electorateId: .electorateId, shortName: .parentElectorateName | match("(.*?)(?:(?: Rural)?(?: City| Shire) Council)").captures[0].string, parentElectorateId: .parentElectorateId, councilName: .parentElectorateName }] | group_by(.parentElectorateId) | map({shortName: .[0].shortName, slug: .[0].shortName | ascii_downcase | split(" ") | join("-"), councilName: .[0].councilName, wardNames: . | map(.name) }) | sort_by(.shortName)' "VEC Data\wards.json" > council_names.json
|
||||
jq '[.[] | {name: .electorateName, electorateId: .electorateId, shortName: .parentElectorateName | match("(.*?)(?:(?: Rural)?(?: City| Shire| Borough) Council)").captures[0].string, parentElectorateId: .parentElectorateId, councilName: .parentElectorateName }] | group_by(.parentElectorateId) | map({shortName: .[0].shortName, slug: .[0].shortName | ascii_downcase | split(" ") | join("-"), councilName: .[0].councilName, wardNames: . | map(.name) }) | sort_by(.shortName)' "VEC Data\wards.json" > council_names.json
|
||||
```
|
||||
|
||||
## lga-links-filter
|
||||
|
||||
@@ -786,6 +786,14 @@
|
||||
"Beaufort"
|
||||
]
|
||||
},
|
||||
{
|
||||
"shortName": "Queenscliffe",
|
||||
"slug": "queenscliffe",
|
||||
"councilName": "Queenscliffe Borough Council",
|
||||
"wardNames": [
|
||||
"Unsubdivided"
|
||||
]
|
||||
},
|
||||
{
|
||||
"shortName": "South Gippsland",
|
||||
"slug": "south-gippsland",
|
||||
|
||||
144
csv-generic/gen-generic.php
Normal file
144
csv-generic/gen-generic.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
require_once("parse_generic_csv.php");
|
||||
|
||||
$options = getopt("", ["generic-csv:", "config-files:"]);
|
||||
|
||||
if (isset($options['generic-csv'])) {
|
||||
$generic_csv = $options['generic-csv'];
|
||||
} else {
|
||||
error_log("Error: Missing required option '--generic-csv'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (isset($options['config-files'])) {
|
||||
$config_files = $options['config-files'];
|
||||
} else {
|
||||
error_log("Error: Missing required option '--config-files'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$config_files = explode(" ", $config_files);
|
||||
$candidate_data = parse_generic_csv($generic_csv);
|
||||
|
||||
$lga_list = [];
|
||||
/* Generate dictionary of LGAs and Wards */
|
||||
foreach ($config_files as $config_file) {
|
||||
$config_string = file_get_contents($config_file);
|
||||
if ($config_string !== FALSE) {
|
||||
$config = json_decode($config_string, true);
|
||||
} else {
|
||||
error_log("Error opening config.json.");
|
||||
exit(1);
|
||||
}
|
||||
$config['config-file'] = $config_file;
|
||||
$lga_list[] = $config;
|
||||
}
|
||||
|
||||
/* Match user typed LGA/Ward to our database */
|
||||
match_lga($candidate_data, $lga_list);
|
||||
|
||||
/* Calculate score for candidate */
|
||||
foreach ($candidate_data as $key => $candidate) {
|
||||
$score = 0;
|
||||
|
||||
if ($candidate['Pledge'] === "y") $score++;
|
||||
if ($candidate['q1'] === "Yes") $score++;
|
||||
if ($candidate['q3'] === "Yes") $score++;
|
||||
if ($candidate['q4'] === "Yes") $score++;
|
||||
if ($candidate['q7'] === "Yes") $score++;
|
||||
|
||||
$candidate_data[$key]['Score'] = $score;
|
||||
}
|
||||
|
||||
$header = ["Ward", "Candidate Name", "Rating", "Pledge", "Picture"];
|
||||
|
||||
/* Generate candidates-generic.csv */
|
||||
foreach ($lga_list as $lga) {
|
||||
$lga_candidates = array_filter($candidate_data, function ($candidate) use ($lga) {
|
||||
return $candidate['match_lga'] === $lga['slug'];
|
||||
});
|
||||
|
||||
if (count($lga_candidates) === 0) continue;
|
||||
|
||||
remove_duplicates($lga_candidates);
|
||||
|
||||
$dir = dirname($lga['config-file']);
|
||||
$dir_files = scandir($dir);
|
||||
$output_file = $dir."/candidates-generic.csv";
|
||||
$override_file = $dir."/candidates-override.csv";
|
||||
|
||||
if (($handle = fopen($output_file, "w")) === FALSE) {
|
||||
error_log('Error opening output file');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fputcsv($handle, $header) === FALSE) {
|
||||
error_log('Error writing headers to output file');
|
||||
exit(3);
|
||||
}
|
||||
|
||||
$lines = [];
|
||||
foreach ($lga_candidates as $candidate) {
|
||||
/* Add extension to photo hash */
|
||||
if (strlen($candidate['Photo'])) {
|
||||
foreach ($dir_files as $file) {
|
||||
if (preg_match("/\.json$/", $file)) continue;
|
||||
if (strstr($file, $candidate['Photo'])) {
|
||||
$candidate['Photo'] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lines[] = [
|
||||
$candidate['match_ward'],
|
||||
$candidate['Name'],
|
||||
$candidate['Score'],
|
||||
$candidate['Pledge'],
|
||||
$candidate['Photo'],
|
||||
];
|
||||
}
|
||||
|
||||
/* Apply overrides if they exist */
|
||||
$overrides = [];
|
||||
if (file_exists($override_file)) {
|
||||
if (($ovr_handle = fopen($override_file, "r")) !== FALSE) {
|
||||
$headers = fgetcsv($ovr_handle);
|
||||
while (($data = fgetcsv($ovr_handle)) !== FALSE) {
|
||||
$override = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
$override[$value] = $data[$key];
|
||||
}
|
||||
$overrides[] = $override;
|
||||
}
|
||||
fclose($ovr_handle);
|
||||
} else {
|
||||
error_log('Error opening overrides file');
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($overrides as $override) {
|
||||
foreach ($lines as $line_key => $line) {
|
||||
$match_index = array_search($override['Match Field'], $header);
|
||||
$replace_index = array_search($override['Replace Field'], $header);
|
||||
if ($line[$match_index] === $override['Match Value']) {
|
||||
if ($replace_index !== false)
|
||||
$lines[$line_key][$replace_index] = $override['Replace Value'];
|
||||
else /* If 'Replace Field' is not matched - delete this entry */
|
||||
$lines[$line_key]['Delete'] = 'y';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if (isset($line['Delete'])) continue;
|
||||
if (fputcsv($handle, $line) === FALSE) {
|
||||
error_log('Error writing candidate to output file');
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
54
csv-generic/gen-image-map.php
Normal file
54
csv-generic/gen-image-map.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
require_once("parse_generic_csv.php");
|
||||
|
||||
$options = getopt("", ["generic-csv:", "config-files:"]);
|
||||
|
||||
if (isset($options['generic-csv'])) {
|
||||
$generic_csv = $options['generic-csv'];
|
||||
} else {
|
||||
error_log("Error: Missing required option '--generic-csv'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (isset($options['config-files'])) {
|
||||
$config_files = $options['config-files'];
|
||||
} else {
|
||||
error_log("Error: Missing required option '--config-files'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$config_files = explode(" ", $config_files);
|
||||
$candidate_data = parse_generic_csv($generic_csv);
|
||||
|
||||
$lga_list = [];
|
||||
/* Generate dictionary of LGAs and Wards */
|
||||
foreach ($config_files as $config_file) {
|
||||
$config_string = file_get_contents($config_file);
|
||||
if ($config_string !== FALSE) {
|
||||
$config = json_decode($config_string, true);
|
||||
} else {
|
||||
error_log("Error opening config.json.");
|
||||
exit(1);
|
||||
}
|
||||
$config['config-file'] = $config_file;
|
||||
$lga_list[] = $config;
|
||||
}
|
||||
|
||||
/* Match user typed LGA/Ward to our database */
|
||||
match_lga($candidate_data, $lga_list);
|
||||
|
||||
$image_map = [];
|
||||
foreach ($candidate_data as $candidate) {
|
||||
if (strlen($candidate['photo_url'])) {
|
||||
$map['url'] = $candidate['photo_url'];
|
||||
$map['match_lga'] = $candidate['match_lga'];
|
||||
$image_map[$candidate['Photo']] = $map;
|
||||
}
|
||||
}
|
||||
|
||||
$json_data = json_encode($image_map);
|
||||
|
||||
print_r($json_data);
|
||||
|
||||
exit(0);
|
||||
107
csv-generic/parse_generic_csv.php
Normal file
107
csv-generic/parse_generic_csv.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
function parse_generic_csv($generic_csv) {
|
||||
$candidate_data = [];
|
||||
if (($handle = fopen($generic_csv, "r")) !== FALSE) {
|
||||
$headers = fgetcsv($handle);
|
||||
while (($data = fgetcsv($handle)) !== FALSE) {
|
||||
$candidate = [];
|
||||
$question_no = 0;
|
||||
$is_question = false;
|
||||
foreach ($headers as $key => $value) {
|
||||
/* Override key name for questions */
|
||||
if ($value === "Verified") {
|
||||
$is_question = false;
|
||||
}
|
||||
|
||||
if (strstr($value, "candidate photo")) $value = "Photo";
|
||||
if (strstr($value, "In which Local Government Area")) $value = "LGA";
|
||||
if (strstr($value, "In which Ward")) $value = "Ward";
|
||||
if (strstr($value, "Political Party")) $value = "Party";
|
||||
|
||||
if ($value === "Pledge") {
|
||||
if (strstr($data[$key], "I pledge")) $data[$key] = "y";
|
||||
else $data[$key] = "n";
|
||||
}
|
||||
|
||||
if ($value === "Photo") {
|
||||
$candidate['photo_url'] = $data[$key];
|
||||
$data[$key] = preg_filter("/.*id=/", "", $data[$key]);
|
||||
}
|
||||
|
||||
if ($is_question) {
|
||||
$candidate['q'.$question_no++] = $data[$key];
|
||||
} else {
|
||||
$candidate[$value] = $data[$key];
|
||||
}
|
||||
|
||||
if ($value === "Pledge") {
|
||||
$is_question = true;
|
||||
}
|
||||
}
|
||||
$candidate_data[] = $candidate;
|
||||
}
|
||||
fclose($handle);
|
||||
} else {
|
||||
error_log('Error opening candidates file');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return $candidate_data;
|
||||
}
|
||||
|
||||
function match_lga(&$candidate_data, $lga_list) {
|
||||
foreach ($candidate_data as &$candidate) {
|
||||
/* Match user typed LGA/Ward to our database */
|
||||
$max_score = 0;
|
||||
foreach ($lga_list as $lga) {
|
||||
$aa = preg_split("/[^a-z]/", strtolower($candidate['LGA']));
|
||||
$bb = preg_split("/[^a-z]/", $lga['slug']);
|
||||
|
||||
$score_sum = 0;
|
||||
foreach ($aa as $a) {
|
||||
foreach ($bb as $b) {
|
||||
similar_text($a, $b, $score);
|
||||
if ($score > 70) $score_sum += $score;
|
||||
else $score_sum -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($score_sum > $max_score) {
|
||||
$max_score = $score_sum;
|
||||
$match_lga = $lga;
|
||||
}
|
||||
}
|
||||
|
||||
$max_score = 0;
|
||||
foreach ($match_lga['wardNames'] as $ward) {
|
||||
similar_text(strtolower($ward), strtolower($candidate['Ward']), $score);
|
||||
if ($score >= $max_score) {
|
||||
$max_score = $score;
|
||||
$match_ward = $ward;
|
||||
}
|
||||
}
|
||||
|
||||
$candidate['match_lga'] = $match_lga['slug'];
|
||||
$candidate['match_ward'] = $match_ward;
|
||||
}
|
||||
}
|
||||
|
||||
function remove_duplicates(&$candidate_data) {
|
||||
$names = [];
|
||||
$duplicates = [];
|
||||
foreach ($candidate_data as $candidate_key => $candidate) {
|
||||
/* If we've already had this name, remove the old entry */
|
||||
foreach ($names as $name_key => $name) {
|
||||
similar_text(strtolower($name), strtolower($candidate['Name']), $score);
|
||||
if ($score > 90) {
|
||||
$duplicates[] = $name_key;
|
||||
}
|
||||
}
|
||||
$names[$candidate_key] = $candidate['Name'];
|
||||
}
|
||||
$duplicates = array_unique($duplicates);
|
||||
foreach ($duplicates as $duplicate) {
|
||||
unset($candidate_data[$duplicate]);
|
||||
}
|
||||
}
|
||||
@@ -77,9 +77,28 @@ if (($handle = fopen($inputFile, "r")) !== FALSE) {
|
||||
if ($currentWard == "Coastal-promontory") {
|
||||
$currentWard = "Coastal-Promontory";
|
||||
}
|
||||
if ($currentWard == "East Gippsland Shire") {
|
||||
$currentWard = "Unsubdivided";
|
||||
}
|
||||
if ($currentWard == "Alpine Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Ararat Rural City") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Benalla Rural City") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Campaspe Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Colac Otway Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "East Gippsland Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Gannawarra Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Glenelg Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Golden Plains Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Hepburn Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Indigo Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Mansfield Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Melbourne City") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Moira Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Moorabool Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Moyne Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Queenscliffe Borough") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Southern Grampians Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Strathbogie Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Swan Hill Rural City") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "Towong Shire") $currentWard = "Unsubdivided";
|
||||
if ($currentWard == "West Wimmera Shire") $currentWard = "Unsubdivided";
|
||||
}
|
||||
if (trim($data[0]) == "Candidate" || trim($data[0]) == "") {
|
||||
if ($currentWard == null) {
|
||||
@@ -96,19 +115,31 @@ if (($handle = fopen($inputFile, "r")) !== FALSE) {
|
||||
|
||||
//print("Adding candidate " . $candidateName . " to ". $currentWard . "\n");
|
||||
|
||||
$name_split = explode(" ", str_replace(",", "", str_replace("'", "_", $data[1])));
|
||||
$name_split = array_values(array_filter(explode(" ", str_replace(",", "", str_replace("'", "_", $data[1]))), function($value) { return !is_null($value) && $value !== ''; }));
|
||||
|
||||
$name_patterns = [
|
||||
implode(".*", $name_split),
|
||||
implode(".*", array_reverse($name_split)),
|
||||
".*" . implode(".*", $name_split) . ".*",
|
||||
".*" . implode(".*", array_reverse($name_split)) . ".*"
|
||||
];
|
||||
|
||||
$regex_groups = array_map(function($x) { return "(?:.*" . $x . ".*)"; }, $name_patterns);
|
||||
$first_name = $name_split[0];
|
||||
$last_name = $name_split[array_key_last($name_split)];
|
||||
|
||||
if (strlen($first_name) > 3) {
|
||||
$name_patterns[] = "^" . $first_name . ".*";
|
||||
}
|
||||
if ($last_name != $first_name && strlen($last_name)) {
|
||||
$name_patterns[] = "^" . $last_name . ".*";
|
||||
}
|
||||
|
||||
$regex_groups = array_map(function($x) { return "(?:" . $x . ")"; }, $name_patterns);
|
||||
|
||||
$regex_pattern = "/" . implode("|", $regex_groups) . "/i";
|
||||
|
||||
$picture = "";
|
||||
foreach ($mediaFiles as $mediaFile) {
|
||||
if ($mediaFile == ".") continue;
|
||||
if ($mediaFile == "..") continue;
|
||||
if (preg_match($regex_pattern, $mediaFile)) {
|
||||
$picture = $mediaFile;
|
||||
break;
|
||||
|
||||
62
get-generic.sh
Executable file
62
get-generic.sh
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
|
||||
#rclone sync --progress bikewest:spl_generic_survey_2024 $DATA_LOC/google-data
|
||||
|
||||
GENERIC_SURVEY=../generic-survey/responses.csv
|
||||
IMAGES=../generic-survey/images
|
||||
|
||||
DATA_PATH="../spl-data"
|
||||
|
||||
echo "Fetching latest responses to generic survey."
|
||||
rm -f $GENERIC_SURVEY # Force re-fetch
|
||||
rclone -v copyto --drive-export-formats csv 'bikewest:spl_generic_survey_2024/Streets People Love council election candidate pledge and survey (Responses).csv' $GENERIC_SURVEY
|
||||
|
||||
config_files=()
|
||||
for folder in "$DATA_PATH"/*; do
|
||||
if test -f "$folder"/config.json; then
|
||||
config_files+=("$folder"/config.json)
|
||||
fi
|
||||
done
|
||||
|
||||
image_map=$(php csv-generic/gen-image-map.php --generic-csv $GENERIC_SURVEY --config-files "${config_files[*]}")
|
||||
|
||||
img_list=()
|
||||
for key in $(jq -r 'keys[]' <<< $image_map) ; do
|
||||
if [ -f $IMAGES/$key ] ; then
|
||||
continue
|
||||
fi
|
||||
img_list+=($key)
|
||||
img_list+=($IMAGES/$key)
|
||||
done
|
||||
|
||||
if [ ${#img_list[*]} -gt 0 ] ; then
|
||||
echo "Downloading $((${#img_list[*]}/2)) image(s)..."
|
||||
rclone -v backend copyid bikewest: ${img_list[*]}
|
||||
fi
|
||||
|
||||
for key in $(jq -r 'keys[]' <<< $image_map) ; do
|
||||
format=$(identify $IMAGES/$key | awk '{print $2}')
|
||||
|
||||
case $format in
|
||||
PNG ) suffix=.png ;;
|
||||
JPEG ) suffix=.jpg ;;
|
||||
HEIC ) suffix=.jpg ;;
|
||||
WEBP ) suffix=.png ;;
|
||||
*)
|
||||
echo "Error: Unknown image format: $IMAGES/$key"
|
||||
;;
|
||||
esac
|
||||
|
||||
lga=$(jq -r ".[\"$key\"][\"match_lga\"]" <<< $image_map)
|
||||
dst="$DATA_PATH/$lga/$key$suffix"
|
||||
|
||||
if [ -f $dst ] ; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Resizing $dst"
|
||||
convert $IMAGES/$key -resize 400x400 $dst
|
||||
done
|
||||
|
||||
echo "Generating candidates-generic.csv files."
|
||||
php csv-generic/gen-generic.php --generic-csv $GENERIC_SURVEY --config-files "${config_files[*]}"
|
||||
50
lga-page.php
Normal file
50
lga-page.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
$options = getopt("", ["candidates-files:", "lga-files:"]);
|
||||
|
||||
if (isset($options['candidates-files'])) {
|
||||
$candidates_files = explode(" ", $options['candidates-files']);
|
||||
} else {
|
||||
error_log("Error: Missing required option '--candidates-files'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (isset($options['lga-files'])) {
|
||||
$lga_files = explode(" ", $options['lga-files']);
|
||||
} else {
|
||||
error_log("Error: Missing required option '--lga-files'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$lgas_with_data = [];
|
||||
foreach ($candidates_files as $file) {
|
||||
$lgas_with_data[] = basename(dirname($file));
|
||||
}
|
||||
|
||||
print('<!-- wp:list --> <ul class="wp-block-list">' . "\n");
|
||||
|
||||
foreach ($lga_files as $config_file) {
|
||||
$config_string = file_get_contents($config_file);
|
||||
|
||||
if ($config_string !== FALSE) {
|
||||
$config = json_decode($config_string, true);
|
||||
} else {
|
||||
error_log("Error opening config.json.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (array_search($config['slug'], $lgas_with_data) === false)
|
||||
$font_weight = 300;
|
||||
else
|
||||
$font_weight = 700;
|
||||
|
||||
print('<!-- wp:list-item {"style":{"typography":{"fontStyle":"normal","fontWeight":"');
|
||||
print($font_weight . '"}}} -->' . "\n");
|
||||
print('<li style="font-style:normal;font-weight:' . $font_weight . '">');
|
||||
print('<a href="' . $config['slug'] . '">' . $config['councilName'] . "</a></li>\n");
|
||||
print('<!-- /wp:list-item -->' . "\n");
|
||||
}
|
||||
|
||||
print('</ul> <!-- /wp:list -->');
|
||||
|
||||
exit(0);
|
||||
@@ -7,7 +7,7 @@
|
||||
DATA_PATH="../spl-data"
|
||||
|
||||
# Controls the flags that are passed to every usage of the wp command.
|
||||
WP_FLAGS="--allow-root --path=/var/www/html"
|
||||
#WP_FLAGS="--allow-root --path=/var/www/html"
|
||||
|
||||
function create_or_update_page() {
|
||||
local council_block="$1"
|
||||
@@ -31,7 +31,20 @@ function create_or_update_page() {
|
||||
|
||||
jq -n '[inputs | { (input_filename | sub("\\.json$"; "") | sub("^.+/"; "")): . }] | reduce .[] as $item ({}; . + $item)' "${media_inputs[@]}" > "$DATA_PATH"/$slug/media.json
|
||||
|
||||
content=$(echo "$council_block" | jq -c | php php-template/main.php --council-file "php://stdin" --candidates-file "$DATA_PATH"/$slug/candidates.csv --media-file "$DATA_PATH"/$slug/media.json )
|
||||
# Community groups get priority
|
||||
if test -f "$DATA_PATH"/$slug/candidates.csv; then
|
||||
candidates_file="$DATA_PATH"/$slug/candidates.csv
|
||||
else
|
||||
candidates_file="$DATA_PATH"/$slug/candidates-generic.csv
|
||||
fi
|
||||
|
||||
if test -f "$DATA_PATH"/$slug/candidates-elected.csv; then
|
||||
candidates_elected_file="$DATA_PATH"/$slug/candidates-elected.csv
|
||||
echo "Found candidates-elected.csv"
|
||||
fi
|
||||
|
||||
|
||||
content=$(echo "$council_block" | jq -c | php php-template/main.php --council-file "php://stdin" --candidates-file "$candidates_file" --media-file "$DATA_PATH"/$slug/media.json --candidates-elected-file "$candidates_elected_file" )
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
|
||||
@@ -40,7 +53,7 @@ function create_or_update_page() {
|
||||
echo "$content" | wp post update "$page_id" --post_content="$content" $WP_FLAGS -
|
||||
else
|
||||
echo "Create page $short_name"
|
||||
echo "$content" | wp post create --post_type=page --post_title="$short_name" --post_status=publish $WP_FLAGS -
|
||||
echo "$content" | wp post create --post_type=page --post_title="$short_name" --post_status=draft $WP_FLAGS -
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
25
make-lga-page.sh
Executable file
25
make-lga-page.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script uses the jq, wp, and php commands, make sure they are installed before running this script.
|
||||
|
||||
# The folder containing data for each council.
|
||||
# Includes the list of candidates and any media.
|
||||
DATA_PATH="../spl-data"
|
||||
|
||||
# Iterate over folders in data path
|
||||
candidates_files=()
|
||||
for folder in "$DATA_PATH"/*; do
|
||||
if test -f "$folder"/candidates-generic.csv; then
|
||||
candidates_files+=("$folder"/candidates-generic.csv)
|
||||
elif test -f "$folder"/candidates.csv; then
|
||||
candidates_files+=("$folder"/candidates.csv)
|
||||
fi
|
||||
if test -f "$folder"/config.json; then
|
||||
lga_files+=("$folder"/config.json)
|
||||
fi
|
||||
done
|
||||
|
||||
content=$(php lga-page.php --candidates-files "${candidates_files[*]}" \
|
||||
--lga-files "${lga_files[*]}")
|
||||
|
||||
echo "$content" | wp post update 465 -
|
||||
@@ -5,15 +5,21 @@
|
||||
# The folder containing data for each council.
|
||||
# Includes the list of candidates and any media.
|
||||
DATA_PATH="../spl-data"
|
||||
DEFAULT_IMAGE="../spl-data/default.png.json"
|
||||
|
||||
# Iterate over folders in data path
|
||||
candidates_files=()
|
||||
for folder in "$DATA_PATH"/*; do
|
||||
if test -f "$folder"/candidates-generic.csv; then
|
||||
candidates_files+=("$folder"/candidates-generic.csv)
|
||||
fi
|
||||
# Community groups get priority
|
||||
if test -f "$folder"/candidates.csv; then
|
||||
candidates_files+=("$folder"/candidates.csv)
|
||||
fi
|
||||
done
|
||||
|
||||
content=$(php pledge-update/pledge-page.php --candidates-files "${candidates_files[*]}")
|
||||
content=$(php pledge-update/pledge-page.php --candidates-files "${candidates_files[*]}" \
|
||||
--default-image $DEFAULT_IMAGE)
|
||||
|
||||
wp post update 12106 --post_content="$content"
|
||||
echo "$content" | wp post update 12106 -
|
||||
|
||||
2
map-generator/dist/main.js
vendored
2
map-generator/dist/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
import polylabel from 'polylabel';
|
||||
|
||||
function normaliseCouncilName(str) {
|
||||
const regex = /(.*?)(?:(?: Rural)?(?: City| Shire) Council)/g;
|
||||
const regex = /(.*?)(?:(?: Rural)?(?: City| Shire| Borough) Council)/g;
|
||||
const matches = str.matchAll(regex);
|
||||
|
||||
// If we get a match, convert to slug format
|
||||
|
||||
2
php-template/example-candidates-elected.csv
Normal file
2
php-template/example-candidates-elected.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Ward,Candidate Name,Elected
|
||||
Harvester,Joe Blogs,y
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
require_once "page_renderer.php";
|
||||
|
||||
$options = getopt("", ["council-file:", "candidates-file:", "media-file:"]);
|
||||
$options = getopt("", ["council-file:", "candidates-file:", "media-file:", "candidates-elected-file:"]);
|
||||
|
||||
if (isset($options['council-file'])) {
|
||||
$councilFileContents = file_get_contents($options['council-file']);
|
||||
@@ -55,6 +55,37 @@ if (isset($options['media-file'])) {
|
||||
|
||||
$mediaData = json_decode($mediaFileContents, true);
|
||||
|
||||
// Merge elected data (if present) into candidate objects
|
||||
if (isset($options['candidates-elected-file'])) {
|
||||
$candidatesElectedFile = $options['candidates-elected-file'];
|
||||
|
||||
if (file_exists($candidatesElectedFile)) {
|
||||
if (($handle = fopen($candidatesElectedFile, "r")) !== FALSE) {
|
||||
$headers = fgetcsv($handle);
|
||||
while (($data = fgetcsv($handle)) !== FALSE) {
|
||||
$electedCandidate = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
$electedCandidate[$value] = $data[$key];
|
||||
}
|
||||
foreach ($candidateData as &$candidate) {
|
||||
if ($candidate["Candidate Name"] == $electedCandidate["Candidate Name"]) {
|
||||
if ($electedCandidate["Elected"] == "y") {
|
||||
$candidate["Elected"] = True;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
} else {
|
||||
error_log('Error opening candidates elected file');
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
error_log("The specified candidates elected file does not exist, will not show any elected candidates for " . $councilData["shortName"] . ".");
|
||||
}
|
||||
}
|
||||
|
||||
$renderer = new SPLPageRenderer();
|
||||
$pageContent = $renderer->renderCouncilPage($councilData, $candidateData, $mediaData);
|
||||
if ($pageContent === null) {
|
||||
|
||||
@@ -12,11 +12,19 @@ if (isset($config["survey"])) {
|
||||
?>
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<?php if (isset($config['header'])): ?>
|
||||
|
||||
<p><?php echo $config['header']; ?></p>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p>The Streets People Love campaign has created scorecards for candidates in the 2024 council elections. Scorecards have been generated based on a candidate's engagement with the Streets People Love campaign, their commitment to our pledge, their responses to a survey and input from campaign members located in the local government area in which they are running.</p>
|
||||
<!-- /wp:paragraph -->
|
||||
|
||||
<!-- wp:paragraph -->
|
||||
<p>Can't see a candidate you know is running? Candidates who don't take our survey won't appear on this page. Feel free to send your local candidates the <?php echo $surveyLink; ?> and let them know it's important to local residents that they do take part, so that we can vote for those who want to build the streets people love.</p>
|
||||
|
||||
<?php endif; ?>
|
||||
<!-- /wp:paragraph -->
|
||||
|
||||
<?php if (isset($media["header.jpg"])): ?>
|
||||
@@ -143,6 +151,12 @@ if (isset($config["survey"])) {
|
||||
<?php
|
||||
$candidate = $chunk[$columnIdx];
|
||||
|
||||
if (isset($candidate["Elected"]) && $candidate["Elected"]) {
|
||||
$candidate_elected = true;
|
||||
} else {
|
||||
$candidate_elected = false;
|
||||
}
|
||||
|
||||
if (isset($candidate['Picture']) && isset($media[$candidate['Picture']])) {
|
||||
$candidate_image = $media[$candidate['Picture']];
|
||||
} else {
|
||||
@@ -162,7 +176,11 @@ if (isset($config["survey"])) {
|
||||
?>
|
||||
|
||||
<!-- wp:image {"id":<?php echo $candidate_image['id']; ?>,"width":"200px","height":"200px","scale":"cover","align":"center","style":{"color":{}},"className":"is-resized"} -->
|
||||
<figure class="wp-block-image aligncenter is-resized"><img src="<?php echo $candidate_image['url']; ?>" alt="" class="wp-image-<?php echo $candidate_image['id']; ?>" style="object-fit:cover;width:200px;height:200px"/></figure>
|
||||
<figure class="wp-block-image aligncenter is-resized <?php if ($candidate_elected) { echo "elected-candidate"; } ?>"><img src="<?php echo $candidate_image['url']; ?>" alt="" class="wp-image-<?php echo $candidate_image['id']; ?>" style="object-fit:cover;width:200px;height:200px;"/>
|
||||
<?php if ($candidate_elected): ?>
|
||||
<figcaption>ELECTED</figcaption>
|
||||
<?php endif; ?>
|
||||
</figure>
|
||||
<!-- /wp:image -->
|
||||
|
||||
<!-- wp:heading {"textAlign":"center","className":"wp-block-heading has-text-align-center has-medium-font-size","style":{"spacing":{"margin":{"top":"1rem","bottom":"0.5rem"}}}} -->
|
||||
|
||||
@@ -11,11 +11,11 @@ if (isset($options['candidates-files'])) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$candidate_data = parse_pledge_data(explode(" ", $candidates_files));
|
||||
$candidate_data = parse_pledge_data(explode(" ", $candidates_files), null);
|
||||
|
||||
/* Select people who have taken the pledge */
|
||||
/* Select people who have taken the pledge (and have an image) */
|
||||
$pledgeCandidates = array_filter($candidate_data, function ($candidate) {
|
||||
return $candidate['Pledge'] === 'y';
|
||||
return $candidate['Pledge'] === 'y' && $candidate['Picture'] !== "";
|
||||
});
|
||||
|
||||
/* Select 9 random candidates */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
class SPLPageRenderer {
|
||||
public function renderPledgePage($councils, $candidates) {
|
||||
public function renderPledgePage($councils, $lga_pages, $candidates) {
|
||||
ob_start();
|
||||
|
||||
$didError = false;
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
<?php
|
||||
|
||||
function parse_pledge_data($candidates_files) {
|
||||
function trim_sluggify($input) {
|
||||
return strtolower(str_replace(' ', '-', trim($input)));
|
||||
}
|
||||
|
||||
function parse_pledge_data($candidates_files, $default_image) {
|
||||
$candidate_data = [];
|
||||
foreach ($candidates_files as $key => $file) {
|
||||
$config_file = dirname($file)."/config.json";
|
||||
$config_string = file_get_contents($config_file);
|
||||
$elected_file = dirname($file)."/candidates-elected.csv";
|
||||
|
||||
if ($config_string !== FALSE) {
|
||||
$config = json_decode($config_string, true);
|
||||
@@ -13,17 +18,49 @@ function parse_pledge_data($candidates_files) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$elected_data = [];
|
||||
if (file_exists($elected_file)) {
|
||||
if (($elected_handle = fopen($elected_file, "r")) !== FALSE) {
|
||||
$headers = fgetcsv($elected_handle);
|
||||
while (($data = fgetcsv($elected_handle)) !== FALSE) {
|
||||
$candidate = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
$candidate[$value] = $data[$key];
|
||||
}
|
||||
$name_slug = trim_sluggify($candidate['Candidate Name']);
|
||||
$elected_data[$name_slug] = $candidate;
|
||||
}
|
||||
} else {
|
||||
error_log('Error opening candidates file');
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (($handle = fopen($file, "r")) !== FALSE) {
|
||||
$headers = fgetcsv($handle);
|
||||
while (($data = fgetcsv($handle)) !== FALSE) {
|
||||
$candidate = [];
|
||||
$candidate['Pledge'] = 'n';
|
||||
$candidate['Picture'] = "";
|
||||
$candidate['image_url'] = "";
|
||||
$candidate['image_id'] = "";
|
||||
if (is_array($default_image)) {
|
||||
$candidate['image_url'] = $default_image['url'];
|
||||
$candidate['image_id'] = $default_image['id'];
|
||||
} else {
|
||||
$candidate['image_url'] = "";
|
||||
$candidate['image_id'] = "";
|
||||
}
|
||||
foreach ($headers as $key => $value) {
|
||||
$candidate[$value] = $data[$key];
|
||||
}
|
||||
$name_slug = trim_sluggify($candidate['Candidate Name']);
|
||||
if (array_key_exists($name_slug, $candidate_data)) {
|
||||
if ($candidate_data[$name_slug]['Pledge'] === 'y') {
|
||||
$candidate['Pledge'] = 'y';
|
||||
}
|
||||
}
|
||||
if (!empty($elected_data) && array_key_exists($name_slug, $elected_data)) {
|
||||
$candidate['Elected'] = $elected_data[$name_slug]['Elected'];
|
||||
}
|
||||
$candidate['Council'] = $config['councilName'];
|
||||
$candidate['Path'] = dirname($file);
|
||||
$media_desc = $candidate['Path']."/".
|
||||
@@ -40,7 +77,7 @@ function parse_pledge_data($candidates_files) {
|
||||
$candidate['image_url'] = $media['url'];
|
||||
$candidate['image_id'] = $media['id'];
|
||||
}
|
||||
$candidate_data[$candidate['Candidate Name']] = $candidate;
|
||||
$candidate_data[$name_slug] = $candidate;
|
||||
}
|
||||
fclose($handle);
|
||||
} else {
|
||||
@@ -59,7 +96,7 @@ function parse_pledge_data($candidates_files) {
|
||||
foreach ($headers as $key => $value) {
|
||||
$candidate[$value] = $data[$key];
|
||||
}
|
||||
$candidate_data[$candidate['Candidate Name']]['Pledge'] =
|
||||
$candidate_data[trim_sluggify($candidate['Candidate Name'])]['Pledge'] =
|
||||
$candidate['Pledge'];
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
require_once("parse_pledge_data.php");
|
||||
require_once("page_renderer.php");
|
||||
|
||||
$options = getopt("", ["candidates-files:"]);
|
||||
$options = getopt("", ["candidates-files:", "default-image:"]);
|
||||
|
||||
if (isset($options['candidates-files'])) {
|
||||
$candidates_files = $options['candidates-files'];
|
||||
@@ -12,7 +12,23 @@ if (isset($options['candidates-files'])) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$candidate_data = parse_pledge_data(explode(" ", $candidates_files));
|
||||
if (isset($options['default-image'])) {
|
||||
$default_image = $options['default-image'];
|
||||
} else {
|
||||
error_log("Error: Missing required option '--default-image'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$default_image = file_get_contents($default_image);
|
||||
|
||||
if ($default_image !== FALSE) {
|
||||
$default_image = json_decode($default_image, true);
|
||||
} else {
|
||||
error_log("Error opening config.json.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$candidate_data = parse_pledge_data(explode(" ", $candidates_files), $default_image);
|
||||
|
||||
/* Select people who have taken the pledge */
|
||||
$pledgeCandidates = array_filter($candidate_data, function ($candidate) {
|
||||
@@ -23,15 +39,22 @@ $renderer = new SPLPageRenderer();
|
||||
//print_r($pledgeCandidates);
|
||||
|
||||
$councils = [];
|
||||
$lga_pages_unsort = [];
|
||||
foreach ($pledgeCandidates as $key => $candidate) {
|
||||
$councils[] = $candidate['Council'];
|
||||
$lga_pages_unsort[] = basename($candidate['Path']);
|
||||
}
|
||||
$councils = array_unique($councils);
|
||||
asort($councils);
|
||||
|
||||
$lga_pages = [];
|
||||
foreach ($councils as $key => $council) {
|
||||
$lga_pages[$key] = $lga_pages_unsort[$key];
|
||||
}
|
||||
|
||||
//print_r($councils);
|
||||
|
||||
$pageContent = $renderer->renderPledgePage($councils, $pledgeCandidates);
|
||||
$pageContent = $renderer->renderPledgePage($councils, $lga_pages, $pledgeCandidates);
|
||||
|
||||
if ($pageContent === null) {
|
||||
exit(2);
|
||||
|
||||
@@ -69,7 +69,7 @@ $councilCount = count($councils);
|
||||
<?php foreach ($councils as $key => $council): ?>
|
||||
<!-- wp:heading {"level":3,"className":"is-style-default"} -->
|
||||
<?php $groupSlug = sluggify($council); ?>
|
||||
<h3 class="wp-block-heading is-style-default" id="<?php echo $groupSlug; ?>"><a style="text-decoration: none;" href="#<?php echo $groupSlug; ?>"><?php echo htmlspecialchars($council); ?></a></h3>
|
||||
<h3 class="wp-block-heading is-style-default" id="<?php echo $groupSlug; ?>"><a style="text-decoration: none;" href="/<?php echo $lga_pages[$key]; ?>"><?php echo htmlspecialchars($council); ?></a></h3>
|
||||
<!-- /wp:heading -->
|
||||
|
||||
<?php
|
||||
@@ -97,6 +97,12 @@ $councilCount = count($councils);
|
||||
<?php
|
||||
$candidate = $chunk[$columnIdx];
|
||||
|
||||
if (isset($candidate['Elected']) && $candidate['Elected'] === 'y') {
|
||||
$candidate_elected = true;
|
||||
} else {
|
||||
$candidate_elected = false;
|
||||
}
|
||||
|
||||
if (isset($candidate['Picture']) && strlen($candidate['image_url'])) {
|
||||
$candidate_image['url'] = $candidate['image_url'];
|
||||
$candidate_image['id'] = $candidate['image_id'];
|
||||
@@ -107,7 +113,11 @@ $councilCount = count($councils);
|
||||
?>
|
||||
|
||||
<!-- wp:image {"id":<?php echo $candidate_image['id']; ?>,"width":"200px","height":"200px","scale":"cover","align":"center","style":{"color":{}},"className":"is-resized"} -->
|
||||
<figure class="wp-block-image aligncenter is-resized"><img src="<?php echo $candidate_image['url']; ?>" alt="" class="wp-image-<?php echo $candidate_image['id']; ?>" style="object-fit:cover;width:200px;height:200px"/></figure>
|
||||
<figure class="wp-block-image aligncenter is-resized <?php if ($candidate_elected) { echo "elected-candidate"; } ?>"><img src="<?php echo $candidate_image['url']; ?>" alt="" class="wp-image-<?php echo $candidate_image['id']; ?>" style="object-fit:cover;width:200px;height:200px;"/>
|
||||
<?php if ($candidate_elected): ?>
|
||||
<figcaption>ELECTED</figcaption>
|
||||
<?php endif; ?>
|
||||
</figure>
|
||||
<!-- /wp:image -->
|
||||
|
||||
<!-- wp:heading {"textAlign":"center","className":"wp-block-heading has-text-align-center has-medium-font-size","style":{"spacing":{"margin":{"top":"1rem","bottom":"0.5rem"}}}} -->
|
||||
|
||||
15
results/fetch.sh
Executable file
15
results/fetch.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p html
|
||||
wget https://www.vec.vic.gov.au/results/2024-council-election-results -O html/lga_list.html
|
||||
|
||||
IFS=$'\n'
|
||||
|
||||
lgas=$(grep 'href="/voting/.*/results"' html/lga_list.html)
|
||||
|
||||
for lga in $lgas ; do
|
||||
lga=$(sed 's|.*href="|https://www.vec.vic.gov.au|' <<< $lga)
|
||||
lga=$(sed 's|">.*||' <<< $lga)
|
||||
file=$(sed 's|.*elections/||' <<< $lga | sed s'|/results||')
|
||||
wget $lga -O html/$file
|
||||
done
|
||||
142
results/gen-elected.php
Normal file
142
results/gen-elected.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
$options = getopt("", ["candidates-files:", "results-file:"]);
|
||||
|
||||
if (isset($options['candidates-files'])) {
|
||||
$candidates_files = $options['candidates-files'];
|
||||
} else {
|
||||
error_log("Error: Missing required option '--candidates-files'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (isset($options['results-file'])) {
|
||||
$results_file = $options['results-file'];
|
||||
$results_string = file_get_contents($results_file);
|
||||
|
||||
if ($results_string !== FALSE) {
|
||||
$results = json_decode($results_string, true);
|
||||
} else {
|
||||
error_log("Error opening results.json.");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
error_log("Error: Missing required option '--results-file'.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
function trim_sluggify($input) {
|
||||
return strtolower(str_replace(' ', '-', trim($input)));
|
||||
}
|
||||
|
||||
function match_words($words, $list) {
|
||||
/* Match database names to VEC names */
|
||||
$max_score = 0;
|
||||
$best_match = "no match";
|
||||
foreach ($list as $possible_match) {
|
||||
$aa = preg_split("/[^a-z]/", strtolower($words));
|
||||
$bb = preg_split("/[^a-z]/", strtolower($possible_match));
|
||||
|
||||
$score_sum = 0;
|
||||
foreach ($aa as $a) {
|
||||
foreach ($bb as $b) {
|
||||
similar_text($a, $b, $score);
|
||||
if ($score > 70) $score_sum += $score;
|
||||
else $score_sum -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($score_sum > $max_score) {
|
||||
$max_score = $score_sum;
|
||||
$best_match = $possible_match;
|
||||
}
|
||||
}
|
||||
return array($max_score, $best_match);
|
||||
}
|
||||
|
||||
$candidates_files = explode(" ", $candidates_files);
|
||||
|
||||
/* Generate dictionary of candidates and LGAs */
|
||||
$candidate_data = [];
|
||||
foreach ($candidates_files as $file) {
|
||||
$config_file = dirname($file)."/config.json";
|
||||
$config_string = file_get_contents($config_file);
|
||||
|
||||
if ($config_string !== FALSE) {
|
||||
$config = json_decode($config_string, true);
|
||||
} else {
|
||||
error_log("Error opening config.json.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$candidate_data[$config['councilName']]['_filename'] = $file;
|
||||
|
||||
if (($handle = fopen($file, "r")) !== FALSE) {
|
||||
$headers = fgetcsv($handle);
|
||||
while (($data = fgetcsv($handle)) !== FALSE) {
|
||||
$candidate = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
$candidate[$value] = $data[$key];
|
||||
}
|
||||
$name_slug = trim_sluggify($candidate['Candidate Name']);
|
||||
$candidate_data[$config['councilName']][$name_slug] = $candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$vec_lga_names = [];
|
||||
foreach ($results as $lga => $data) {
|
||||
$vec_lga_names[] = $lga;
|
||||
}
|
||||
|
||||
function was_elected($candidate, $vec_wards) {
|
||||
foreach ($vec_wards as $vec_candidates) {
|
||||
list($score, $match) = match_words($candidate, $vec_candidates);
|
||||
if ($score > 180) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$header = ["Ward", "Candidate Name", "Elected"];
|
||||
|
||||
foreach ($candidate_data as $lga => $db_candidates) {
|
||||
/* Find LGA in results dict */
|
||||
list($score, $vec_lga_name) = match_words($lga, $vec_lga_names);
|
||||
$vec_wards = $results[$vec_lga_name];
|
||||
|
||||
$elected = [];
|
||||
/* Go through database candidates and build list of elected candidates */
|
||||
foreach ($db_candidates as $key => $value) {
|
||||
if ($key === '_filename') {
|
||||
$output_file = dirname($value)."/candidates-elected.csv";
|
||||
continue;
|
||||
}
|
||||
if (was_elected($value['Candidate Name'], $vec_wards)) {
|
||||
$elected[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't create file if none were elected. */
|
||||
if (count($elected) === 0) continue;
|
||||
|
||||
if (($handle = fopen($output_file, "w")) === FALSE) {
|
||||
error_log('Error opening output file');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fputcsv($handle, $header) === FALSE) {
|
||||
error_log('Error writing headers to output file');
|
||||
exit(3);
|
||||
}
|
||||
|
||||
foreach ($elected as $candidate) {
|
||||
$line = array($candidate['Ward'], $candidate['Candidate Name'], "y");
|
||||
if (fputcsv($handle, $line) === FALSE) {
|
||||
error_log('Error writing candidate to output file');
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
53
results/parser.py
Normal file
53
results/parser.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from bs4 import BeautifulSoup, Tag as HTMLTag
|
||||
import json, re, argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('filenames', nargs='*')
|
||||
args = parser.parse_args()
|
||||
|
||||
def get_vacancies(ward):
|
||||
text = ward.parent.parent.h2.text
|
||||
ward_name = re.search("[^\(]*", text)[0].strip()
|
||||
vacancies = int(re.search("\([0-9]+", text)[0].strip("("))
|
||||
return (ward_name, vacancies, ward)
|
||||
|
||||
def get_candidate_names(ward_desc):
|
||||
names = []
|
||||
for sibling in ward_desc[2].parent.next_siblings:
|
||||
if not isinstance(sibling, HTMLTag):
|
||||
continue
|
||||
if not (blocks := sibling.find_all('td', class_="list-item-body")):
|
||||
continue
|
||||
for block in blocks:
|
||||
names.append(re.sub('\n.*', '', block.text.strip()))
|
||||
return names
|
||||
|
||||
def parse_lga(filename):
|
||||
with open(filename, 'r') as results_fp:
|
||||
html_doc = results_fp.read()
|
||||
|
||||
soup = BeautifulSoup(html_doc, 'html.parser')
|
||||
wards0 = soup.find_all(string="Successful candidates")
|
||||
wards1 = soup.find_all(string="Elected candidates")
|
||||
|
||||
ward_info = []
|
||||
for ward in wards0:
|
||||
ward_info.append(get_vacancies(ward))
|
||||
for ward in wards1:
|
||||
ward_info.append(get_vacancies(ward))
|
||||
|
||||
results = {}
|
||||
for ward in ward_info:
|
||||
names = get_candidate_names(ward)
|
||||
assert len(names) == ward[1]
|
||||
results[ward[0]] = names
|
||||
|
||||
return results
|
||||
|
||||
all_results = {}
|
||||
for lga in args.filenames:
|
||||
lga_name = re.sub('html/lgas/', '', lga)
|
||||
results = parse_lga(lga)
|
||||
all_results[lga_name] = results
|
||||
|
||||
print(json.dumps(all_results, indent=4))
|
||||
22
update-elected.sh
Executable file
22
update-elected.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script uses the jq, wp, and php commands, make sure they are installed before running this script.
|
||||
|
||||
# The folder containing data for each council.
|
||||
# Includes the list of candidates and any media.
|
||||
DATA_PATH="../spl-data"
|
||||
|
||||
# Iterate over folders in data path
|
||||
candidates_files=()
|
||||
for folder in "$DATA_PATH"/*; do
|
||||
if test -f "$folder"/candidates-generic.csv; then
|
||||
candidates_files+=("$folder"/candidates-generic.csv)
|
||||
fi
|
||||
# Community groups get priority
|
||||
if test -f "$folder"/candidates.csv; then
|
||||
candidates_files+=("$folder"/candidates.csv)
|
||||
fi
|
||||
done
|
||||
|
||||
php results/gen-elected.php --candidates-files "${candidates_files[*]}" \
|
||||
--results-file $DATA_PATH/results.json
|
||||
@@ -15,6 +15,10 @@ DATA_PATH="../spl-data"
|
||||
|
||||
candidates_files=()
|
||||
for folder in "$DATA_PATH"/*; do
|
||||
if test -f "$folder"/candidates-generic.csv; then
|
||||
candidates_files+=("$folder"/candidates-generic.csv)
|
||||
fi
|
||||
# Community groups get priority
|
||||
if test -f "$folder"/candidates.csv; then
|
||||
candidates_files+=("$folder"/candidates.csv)
|
||||
fi
|
||||
@@ -24,4 +28,4 @@ pledge_sed=$(php pledge-update/homepage.php --candidates-files "${candidates_fil
|
||||
|
||||
content=$(sed "$pledge_sed" ../spl-data/movie-homepage)
|
||||
|
||||
wp post update 1803 --post_content="$content"
|
||||
echo "$content" | wp post update 1803 -
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# Additionally, make sure the wp-cli/restful package is installed in the wp command (via "wp package install wp-cli/restful")
|
||||
|
||||
# Controls the flags that are passed to every usage of the wp command.
|
||||
WP_FLAGS="--allow-root --path=/var/www/html"
|
||||
#WP_FLAGS="--allow-root --path=/var/www/html"
|
||||
|
||||
media_path="$1"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user