summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: b92a0eb671973898cb7511c1f227155f4500eef4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use {
    anyhow::{
        anyhow,
        Result,
    },
    std::{
        env::args,
        fs::File,
        io::prelude::*,
    },
    svg::{
        Document,
        node::{
            Text as TextNode,
            element::{
                Rectangle,
                Text,
            }
        }
    }
};

const COL_WIDTH: f64 = 350.0;
const ROWS: usize = 35;

fn main() -> Result<()> {
    let first_arg = args().nth(1).ok_or_else(|| anyhow!("Missing meetup csv file argument."))?;
    let fullpath = first_arg.clone();
    let filename = fullpath.split('/').last().unwrap_or(&fullpath);
    let (basename, _) = filename.split_once('.')
        .ok_or_else(|| anyhow!("Unexpected filename. Was it downloaded from meetup.com?"))?;
    let (event_name, _) = filename.split_once("_sponsored")
        .ok_or_else(|| anyhow!("Unexpected filename. Was it downloaded from meetup.com?"))?;

    let mut csv_file = File::open(first_arg)?;
    let mut contents = String::new();
    csv_file.read_to_string(&mut contents)?;

    let mut attendees: Vec<String> = vec![];
    let mut waitlisted: Vec<String> = vec![];

    for (n, row) in contents.split('\n').enumerate() {
        let fields: Vec<&str> = row.split('\t').collect();
        match (fields.get(1), fields.get(4)) {
            (Some(name), Some(rsvp)) => { },
            _ => eprintln!("Unparsable row {n}: {}", row),
        // fields.get(5) "Waiting List"
        }
    }

    let page_height = "297mm";
    let page_width = "210mm";
    let x_crop = 60.047f64;
    let y_crop = 110.717f64;
    // let fontfamily = "Liberation Serif";
    let fontfamily = "Iosevka";
    let fontsize = 22.2;

    let title_text = Text::new()
        .set("x", 1.2 * x_crop)
        .set("y", 1.2 * y_crop / 2.0)
        .add(TextNode::new(event_name.chars().map(|c| if c == '_' { ' '} else { c }).collect::<String>()))
        .set("style", format!("font-size:{fontsize}px;line-height:1.25;font-family:'{fontfamily}'"));

    let mut document = Document::new()
        .set("viewBox", (0, 0, page_width, page_height))
        .set("width", page_width)
        .set("height", page_height)
        .set("xmlns:inkscape", "http://www.inkscape.org/namespaces/inkscape")
        .add(title_text);

    for (n, attendee) in contents.split('\n').enumerate() {
        if let Some((name, _)) = attendee.split_once('\t') {
            let row = n % ROWS;
            let col = n / ROWS;

            let attendee_box = Rectangle::new()
                .set("x", 1.2 * x_crop + col as f64 * COL_WIDTH)
                .set("y", 1.2 * y_crop + row as f64 * fontsize * 1.2)
                .set("style", "fill:#ffffff;stroke:#000000;fill-opacity=0.4;opacity=0.4")
                .set("height", fontsize * 1.2)
                .set("width", COL_WIDTH);

            let attendee_text = Text::new()
                .set("x", 1.2 * x_crop + col as f64 * COL_WIDTH + 40.0)
                .set("y", 1.2 * y_crop + fontsize + row as f64 * fontsize * 1.2)
                .add(TextNode::new(name))
                .set("style", format!("font-size:{fontsize}px;line-height:1.25;font-family:'{fontfamily}'"));

            document = document
                .add(attendee_box)
                .add(attendee_text);
        } else {
            if attendee.is_empty() {
                continue;
            }
            return Err(anyhow!("Could not parse: '{attendee}'"));
        }
    }

    svg::save(format!("{basename}.svg"), &document).unwrap();
    Ok(())
}