aboutsummaryrefslogtreecommitdiff
path: root/main.odin
blob: c25ee7ed3150ef8d6c577b74c8057df51899a8d9 (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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package main

import "core:fmt"
import "core:os"
import "core:path/filepath"
import "core:strings"

PART_ONE :: #load("parts/start.html", string)
PART_TWO :: #load("parts/start2.html", string)
PART_END :: #load("parts/end.html", string)

main :: proc() {
	
	input_file_name : string
	if len(os.args) < 2 {
		// Attempt to auto-detect CSVs, but filepath.glob is broken.
		// It doesn't return anything if you run the exe from a PATH folder.
		
		/* fmt.println("No file submitted. Using first CSV found.")
		glob_pattern := fmt.aprintf("{}\\*.*", os.get_current_directory())
		fmt.println(glob_pattern)
		csvs, _ := filepath.glob(glob_pattern)
		fmt.println(csvs)
		input_file_name = csvs[0] */
		fmt.println("ERROR: No file submitted.")
		return
	} else {
		fmt.printf("Input CSV: {}\n", os.args[1])
		input_file_name = os.args[1]
	}
	
	
	// Reading CSV file

	data, ok := os.read_entire_file(input_file_name, context.allocator)
	if !ok {
		fmt.printf("ERROR: Could not read file: {}\n", os.args[1])
		return
	}
	defer delete(data, context.allocator)
	
	total_output: string = PART_ONE // Page title
	total_output = append(total_output, fmt.aprintf("{} - Lydrapport", input_file_name[len(input_file_name)-17:len(input_file_name)-11]))
	total_output = append(total_output, PART_TWO)
	it := string(data)
	
	// First we do a pass to find out at what column the channels start and end,
	// and to find out how many channels we actually use at maximum.
	// This will let us compress the channel columns to only what is needed.
	
	tracks_start := 0
	tracks_end := 0
	max_tracks := 0
	line_index := 0
	for line in strings.split_lines_iterator(&it) {
		tracks_seen_this_line := 0
		for element, e in strings.split(line, ",") {
			if element == "Trk 1" {
				tracks_start = e
				fmt.printf("Tracks start at: {}\n", tracks_start)
			}
			if element == "Notes" {
				tracks_end = e-1
				fmt.printf("Tracks end at: {}\n", tracks_end)
			}
			if e >= tracks_start && tracks_end >= e { // If there's anything in the range of where tracks are, count it
				if element != "" do tracks_seen_this_line += 1
			}
		}
		// Update the max
		if tracks_seen_this_line > max_tracks {
			max_tracks = tracks_seen_this_line
			fmt.printf("Highest track count so far found on line {}, with {} tracks.\n", line_index, max_tracks)
		} 
		line_index += 1
	}
	potensial_tracks := tracks_end+1 - tracks_start
	unused_tracks := potensial_tracks - max_tracks

	// Now we output the HTML.
	
	it = string(data)
	line_index = 0
	blank_lines := 0
	state : states = .TITLE
	time_in_state := 0
	info_reading_to_field := true
	for line in strings.split_lines_iterator(&it) {
		//fmt.printf("state.{} line_index:{} t:{} blank_lines:{} :   \t", state, line_index, time_in_state, blank_lines)
		there_was_content_in_line := false
		
		// Writing the headers and section stuff.
		#partial switch state {
			case .HEADER:
				if time_in_state == 1 do total_output = append(total_output, "    <table>\n      <thead>\n        <tr class=\"header-tr\">\n")
				
			case .BODY:
				total_output = append(total_output, "      <tr>\n")
		}
		
		columns_skipped := 0
		for element, e in strings.split(line, ",") {
			if len(element)> 0 do there_was_content_in_line = true
			if len(element)> 0 do blank_lines = 0
			// Filling the row of data
			switch state {
				case .TITLE:
					//fmt.printf("{}  T  ", element)
				case .INFO:
					//fmt.printf("{}  I  ", element)
					
					if len(element)>0 {
						if info_reading_to_field {
							total_output = append(total_output, fmt.aprintf("      <p><b>{}</b>", element))
						} else {
							total_output = append(total_output, fmt.aprintf(" {}</p>\n", element[1:len(element)-1]))
						}
						info_reading_to_field = !info_reading_to_field
					}
					
				case .HEADER:
					//fmt.printf("{}  H  ", element)
					if time_in_state == 1 {
						if e == 4 { // Magic number to select the default sorting column
							total_output = append(total_output, fmt.aprintf("          <th class=\"current-sort\">{}</th>\n", element))
						} else if e <= tracks_start+max_tracks-1 || e > tracks_end {
							total_output = append(total_output, fmt.aprintf("          <th>{}</th>\n", element))
						}
					}
					
				case .BODY:
					//fmt.printf("{}  B  ", element)
					if e == tracks_end+1 {
						for _ in 0..<(columns_skipped - unused_tracks) { // Add padding so note at end ligns up
							total_output = append(total_output, "        <td></td>\n")
						}
					}
					if element != "" {

						if e >= tracks_start {
							total_output = append(total_output, fmt.aprintf("        <td>{}</td>\n", element[1:len(element)-1]))
						/*} else if e == 0 { // Making filename a link to the file
							total_output = append(total_output, fmt.aprintf("        <td><a href=\"{}\">{}</a></td>\n", element, element))*/
						} else {
							total_output = append(total_output, fmt.aprintf("        <td>{}</td>\n", element))
						}
						
					} else {
						columns_skipped += 1
					}
			}
		}
		// Advancing state machine and finishing off divs n stuff
		switch state {
			case .TITLE:
				if line_index==1 {
					state = .INFO
					time_in_state = 0
				}
			case .INFO:
				if blank_lines > 1 {
					total_output = append(total_output, "    </div>\n  </div>\n")
					state = .HEADER
					time_in_state = 0
				}
			case .HEADER:
				if blank_lines > 0 {
					state = .BODY
					time_in_state = 0
					total_output = append(total_output, "        </tr>\n      </thead>\n      <tbody>\n")
				}
			case .BODY:
				total_output = append(total_output, "      </tr>\n")
		}
		if there_was_content_in_line {
			blank_lines = 0
		} else {
			blank_lines += 1
		}
		//fmt.printf("\n")
		line_index += 1
		time_in_state += 1
	}
	total_output = append(total_output, PART_END)

	output_file_name := fmt.aprintf("{}_Knekt.html", os.args[1][:len(os.args[1])-4])
	os.remove(output_file_name)
	output_file_handle, _ := os.open(output_file_name, os.O_CREATE | os.O_RDWR, 0o777)
	os.write_string(output_file_handle, total_output)
	os.close(output_file_handle)
	
	fmt.printf("Wrote file: {}\n", output_file_name)
	
	/*fmt.printf("\n\n\nTOTAL OUTPUT:\n\n\n")
	fmt.println(total_output)*/
}

append :: proc(input, to_add: string) -> string {
	output := strings.concatenate({input, to_add})
	//delete(to_add)
	//delete(input)
	return output
}

states :: enum {
	TITLE,
	INFO,
	HEADER,
	BODY,
}