mirror of
https://github.com/132nd-vWing/tacview-splitter.git
synced 2026-08-26 12:18:37 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a2a08515b | ||
|
|
3658dbcdf7 | ||
|
|
e9be340a6b | ||
|
|
7e788c66cf | ||
|
|
97df3b46f8 | ||
|
|
902ed24e46 | ||
|
|
64cb0879e2 | ||
|
|
f09fb480ef | ||
|
|
efa43023f4 | ||
|
|
d9695eab02 | ||
|
|
db6af20850 | ||
|
|
467274816f | ||
|
|
67c5e61d21 | ||
|
|
6e192af5ad | ||
|
|
9dc8005d39 | ||
|
|
e2ab2787e7 |
@@ -1,3 +1,9 @@
|
|||||||
|
# build system
|
||||||
|
.built
|
||||||
|
.released
|
||||||
|
.stripped
|
||||||
|
.tested
|
||||||
|
|
||||||
# ---> Rust
|
# ---> Rust
|
||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
|
|||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tacview-splitter"
|
name = "tacview-splitter"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
authors = ["132nd-Professor <132nd-Professor>"]
|
authors = ["132nd-Professor <132nd-Professor>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
zip = ">= 0.5.13"
|
zip = ">= 0.6.2"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|||||||
@@ -6,20 +6,47 @@ RELEASE_WINDOWS=tacview-splitter-win10-x86_64.zip
|
|||||||
BIN_LINUX=target/x86_64-unknown-linux-gnu/release/tacview-splitter
|
BIN_LINUX=target/x86_64-unknown-linux-gnu/release/tacview-splitter
|
||||||
BIN_WINDOWS=target/x86_64-pc-windows-gnu/release/tacview-splitter.exe
|
BIN_WINDOWS=target/x86_64-pc-windows-gnu/release/tacview-splitter.exe
|
||||||
|
|
||||||
|
TEST_FILES=Tacview-20210606-222650-DCS-ATRM_2.7.0.443.txt.acmi Tacview-20210606-222650-DCS-ATRM_2.7.0.443.zip.acmi Tacview-20210608-085030-DCS-Georgia_At_War_v3.0.24_afternoon.txt.acmi Tacview-20210608-085030-DCS-Georgia_At_War_v3.0.24_afternoon.zip.acmi
|
||||||
|
|
||||||
default: release
|
default: release
|
||||||
|
|
||||||
build:
|
.built: src/lib.rs src/main.rs Cargo.toml
|
||||||
cargo build --release --target x86_64-unknown-linux-gnu
|
cargo build --release --target x86_64-unknown-linux-gnu
|
||||||
cargo build --release --target x86_64-pc-windows-gnu
|
cargo build --release --target x86_64-pc-windows-gnu
|
||||||
|
touch .built
|
||||||
|
|
||||||
strip: build
|
build: .built
|
||||||
|
|
||||||
|
.stripped: .built
|
||||||
strip ${BIN_LINUX} ${BIN_WINDOWS}
|
strip ${BIN_LINUX} ${BIN_WINDOWS}
|
||||||
|
touch .stripped
|
||||||
|
|
||||||
release: build strip
|
strip: .stripped
|
||||||
|
|
||||||
|
.tested: .stripped
|
||||||
|
for file in ${TEST_FILES}; do \
|
||||||
|
mkdir -p test; \
|
||||||
|
cp testfiles/$$file test; \
|
||||||
|
cd test; \
|
||||||
|
../${BIN_LINUX}; \
|
||||||
|
cd ../ ; \
|
||||||
|
rm -rf test ; \
|
||||||
|
done
|
||||||
|
touch .tested
|
||||||
|
|
||||||
|
test: .tested
|
||||||
|
|
||||||
|
.released: .tested
|
||||||
rm -rf release;
|
rm -rf release;
|
||||||
mkdir -p release/{windows,linux}/tacview-splitter-${VERSION};
|
mkdir -p release/{windows,linux}/tacview-splitter-${VERSION};
|
||||||
cp ${BIN_LINUX} release/linux/tacview-splitter-${VERSION}
|
cp ${BIN_LINUX} release/linux/tacview-splitter-${VERSION}
|
||||||
cp ${BIN_WINDOWS} release/windows/tacview-splitter-${VERSION}
|
cp ${BIN_WINDOWS} release/windows/tacview-splitter-${VERSION}
|
||||||
cd release/linux; tar -zcvf ${RELEASE_LINUX} tacview-splitter-${VERSION}; cp ${RELEASE_LINUX} ..
|
cd release/linux; tar -zcvf ${RELEASE_LINUX} tacview-splitter-${VERSION}; cp ${RELEASE_LINUX} ..
|
||||||
cd release/windows; 7z a ${RELEASE_WINDOWS} tacview-splitter-${VERSION}; cp ${RELEASE_WINDOWS} ..
|
cd release/windows; 7z a ${RELEASE_WINDOWS} tacview-splitter-${VERSION}; cp ${RELEASE_WINDOWS} ..
|
||||||
cd release; sha256sum ${RELEASE_LINUX} ${RELEASE_WINDOWS} > sha256sums.txt
|
cd release; rm -rf linux windows; sha256sum ${RELEASE_LINUX} ${RELEASE_WINDOWS} > sha256sums.txt
|
||||||
|
touch .released
|
||||||
|
|
||||||
|
release: .released
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf release target test .released .tested .stripped .built
|
||||||
|
|||||||
+70
-21
@@ -1,16 +1,19 @@
|
|||||||
pub mod lib {
|
pub mod lib {
|
||||||
use std::io::Write;
|
use std::collections::HashSet;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
use zip;
|
use zip;
|
||||||
|
|
||||||
const ERR_CANNOT_WRITE_DATA: &str = "Could not write data";
|
const ERR_CANNOT_WRITE_DATA: &str = "Could not write data";
|
||||||
const ERR_CANNOT_OPEN_OUTPUT: &str = "Could not open output file";
|
const ERR_CANNOT_OPEN_OUTPUT: &str = "Could not open output file";
|
||||||
|
const ERR_CANNOT_BEGIN_FILE: &str = "Could not begin file in zip archive";
|
||||||
|
|
||||||
pub struct IDs<'a> {
|
pub struct IDs<'a> {
|
||||||
pub blue: Vec<&'a str>,
|
pub blue: HashSet<&'a str>,
|
||||||
pub red: Vec<&'a str>,
|
pub red: HashSet<&'a str>,
|
||||||
pub violet: Vec<&'a str>,
|
pub violet: HashSet<&'a str>,
|
||||||
pub unknown: Vec<&'a str>,
|
pub unknown: HashSet<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Descriptors<T: Write> {
|
pub struct Descriptors<T: Write> {
|
||||||
@@ -49,50 +52,96 @@ pub mod lib {
|
|||||||
impl<T: Write> Handling for Descriptors<T> {
|
impl<T: Write> Handling for Descriptors<T> {
|
||||||
fn write(&mut self, header: Vec<String>, bodies_by_coalition: BodiesByCoalition) {
|
fn write(&mut self, header: Vec<String>, bodies_by_coalition: BodiesByCoalition) {
|
||||||
for line in &header {
|
for line in &header {
|
||||||
write!(self.blue, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
writeln!(self.blue, "{}", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
write!(self.red, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
writeln!(self.red, "{}", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
write!(self.violet, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
writeln!(self.violet, "{}", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
}
|
}
|
||||||
for line in &bodies_by_coalition.blue {
|
for line in &bodies_by_coalition.blue {
|
||||||
write!(self.blue, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
writeln!(self.blue, "{}", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
}
|
}
|
||||||
for line in &bodies_by_coalition.red {
|
for line in &bodies_by_coalition.red {
|
||||||
write!(self.red, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
writeln!(self.red, "{}", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
}
|
}
|
||||||
for line in &bodies_by_coalition.violet {
|
for line in &bodies_by_coalition.violet {
|
||||||
write!(self.violet, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
writeln!(self.violet, "{}", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Descriptors<fs::File> {
|
impl Descriptors<fs::File> {
|
||||||
pub fn new_for_file(filenames: OutputFilenames) -> Descriptors<fs::File> {
|
pub fn new(filenames: OutputFilenames) -> Descriptors<fs::File> {
|
||||||
let blue = fs::File::create(&filenames.txt.blue).expect(ERR_CANNOT_OPEN_OUTPUT);
|
let blue = fs::File::create(&filenames.txt.blue).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
let red = fs::File::create(&filenames.txt.red).expect(ERR_CANNOT_OPEN_OUTPUT);
|
let red = fs::File::create(&filenames.txt.red).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
let violet = fs::File::create(&filenames.txt.violet).expect(ERR_CANNOT_OPEN_OUTPUT);
|
let violet = fs::File::create(&filenames.txt.violet).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
let descriptors = Descriptors { blue, red, violet };
|
Descriptors { blue, red, violet }
|
||||||
return descriptors
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Descriptors<zip::ZipWriter<fs::File>> {
|
impl Descriptors<zip::ZipWriter<fs::File>> {
|
||||||
pub fn new_for_zip(filenames: OutputFilenames) -> Descriptors<zip::ZipWriter<fs::File>> {
|
pub fn new(filenames: OutputFilenames) -> Descriptors<zip::ZipWriter<fs::File>> {
|
||||||
let options = zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Deflated);
|
let options = zip::write::FileOptions::default()
|
||||||
|
.compression_method(zip::CompressionMethod::Deflated);
|
||||||
|
|
||||||
let file = fs::File::create(&filenames.zip.blue).expect(ERR_CANNOT_OPEN_OUTPUT);
|
let file = fs::File::create(&filenames.zip.blue).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
let mut blue = zip::ZipWriter::new(file);
|
let mut blue = zip::ZipWriter::new(file);
|
||||||
blue.start_file(&filenames.txt.blue, options).unwrap();
|
blue.start_file(&filenames.txt.blue, options)
|
||||||
|
.expect(ERR_CANNOT_BEGIN_FILE);
|
||||||
|
|
||||||
let file = fs::File::create(&filenames.zip.red).expect(ERR_CANNOT_OPEN_OUTPUT);
|
let file = fs::File::create(&filenames.zip.red).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
let mut red = zip::ZipWriter::new(file);
|
let mut red = zip::ZipWriter::new(file);
|
||||||
red.start_file(&filenames.txt.red, options).unwrap();
|
red.start_file(&filenames.txt.red, options)
|
||||||
|
.expect(ERR_CANNOT_BEGIN_FILE);
|
||||||
|
|
||||||
let file = fs::File::create(&filenames.zip.violet).expect(ERR_CANNOT_OPEN_OUTPUT);
|
let file = fs::File::create(&filenames.zip.violet).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
let mut violet = zip::ZipWriter::new(file);
|
let mut violet = zip::ZipWriter::new(file);
|
||||||
violet.start_file(&filenames.txt.violet, options).unwrap();
|
violet
|
||||||
|
.start_file(&filenames.txt.violet, options)
|
||||||
|
.expect(ERR_CANNOT_BEGIN_FILE);
|
||||||
|
|
||||||
let descriptors = Descriptors{blue, red, violet};
|
Descriptors { blue, red, violet }
|
||||||
descriptors
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sanity_check_output_filenames(
|
||||||
|
input_filename: &String,
|
||||||
|
output_filenames: &FilenamesVariant,
|
||||||
|
) {
|
||||||
|
if input_filename == &output_filenames.blue
|
||||||
|
|| input_filename == &output_filenames.red
|
||||||
|
|| input_filename == &output_filenames.violet
|
||||||
|
{
|
||||||
|
panic!("Output filenames were the same as input filenames")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_output_filenames_individual(
|
||||||
|
input_filename: &str,
|
||||||
|
old_extension: &str,
|
||||||
|
new_extension: &str,
|
||||||
|
coalition: &str,
|
||||||
|
) -> String {
|
||||||
|
let mut output_extension = coalition.to_owned();
|
||||||
|
output_extension.push_str(new_extension);
|
||||||
|
input_filename.replace(old_extension, &output_extension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::lib::*;
|
||||||
|
#[test]
|
||||||
|
fn test_get_output_filenames_individual() {
|
||||||
|
let input_filename = "something.txt.acmi".to_string();
|
||||||
|
let extension = ".txt.acmi";
|
||||||
|
let coalition = "_blue";
|
||||||
|
let result =
|
||||||
|
get_output_filenames_individual(&input_filename, extension, extension, coalition);
|
||||||
|
let correct_result = "something_blue.txt.acmi";
|
||||||
|
assert_eq!(result, correct_result);
|
||||||
|
|
||||||
|
let extension_wrong = ".tXT.acmi";
|
||||||
|
let result =
|
||||||
|
get_output_filenames_individual(&input_filename, extension_wrong, extension, coalition);
|
||||||
|
assert_ne!(result, correct_result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+138
-73
@@ -1,19 +1,23 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
use std::{fs, str};
|
use std::{fs, str};
|
||||||
|
|
||||||
use std::io::{BufRead, BufReader};
|
|
||||||
use zip;
|
|
||||||
use tacview_splitter::lib;
|
use tacview_splitter::lib;
|
||||||
use tacview_splitter::lib::Handling;
|
use tacview_splitter::lib::Handling;
|
||||||
|
|
||||||
const COMMENT: char = '#';
|
const COMMENT: char = '#';
|
||||||
const MINUS: char = '-';
|
const MINUS: char = '-';
|
||||||
|
|
||||||
const EXTENSION_ZIP: &str = ".zip.acmi";
|
const EXTENSION_ZIP: &str = ".zip.acmi";
|
||||||
const EXTENSION_TXT: &str = ".txt.acmi";
|
const EXTENSION_TXT: &str = ".txt.acmi";
|
||||||
|
|
||||||
const UNKNOWN: u8 = 0;
|
#[derive(PartialEq)]
|
||||||
const TIMESTAMP: u8 = 1;
|
enum LineType {
|
||||||
const DESTRUCTION: u8 = 2;
|
Unknown,
|
||||||
const TELEMETRY: u8 = 3;
|
Timestamp,
|
||||||
|
Destruction,
|
||||||
|
Telemetry,
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (input_filename, is_zip) = find_input_file();
|
let (input_filename, is_zip) = find_input_file();
|
||||||
@@ -22,12 +26,12 @@ fn main() {
|
|||||||
let (header, body) = split_into_header_and_body(lines);
|
let (header, body) = split_into_header_and_body(lines);
|
||||||
let bodies_by_coalition = divide_body_by_coalition(&body);
|
let bodies_by_coalition = divide_body_by_coalition(&body);
|
||||||
|
|
||||||
let output_filenames = get_output_filenames(&input_filename);
|
let output_filenames = get_output_filenames(&input_filename, is_zip);
|
||||||
if is_zip {
|
if is_zip {
|
||||||
let mut descriptors = lib::Descriptors::new_for_zip(output_filenames);
|
let mut descriptors = lib::Descriptors::<zip::ZipWriter<fs::File>>::new(output_filenames);
|
||||||
descriptors.write(header, bodies_by_coalition);
|
descriptors.write(header, bodies_by_coalition);
|
||||||
} else {
|
} else {
|
||||||
let mut descriptors = lib::Descriptors::new_for_file(output_filenames);
|
let mut descriptors = lib::Descriptors::<fs::File>::new(output_filenames);
|
||||||
descriptors.write(header, bodies_by_coalition);
|
descriptors.write(header, bodies_by_coalition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,34 +39,44 @@ fn main() {
|
|||||||
fn split_into_header_and_body(lines: Vec<String>) -> (Vec<String>, Vec<String>) {
|
fn split_into_header_and_body(lines: Vec<String>) -> (Vec<String>, Vec<String>) {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for line in &lines {
|
for line in &lines {
|
||||||
if line.chars().nth(0).expect("malformed line") == COMMENT {
|
if line.chars().next().expect("malformed line") == COMMENT {
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
return (lines[..i].to_vec(), lines[i..].to_vec());
|
(lines[..i].to_vec(), lines[i..].to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divide_body_by_coalition(body: &Vec<String>) -> lib::BodiesByCoalition {
|
fn divide_body_by_coalition(body: &Vec<String>) -> lib::BodiesByCoalition {
|
||||||
let mut bbc = lib::BodiesByCoalition{blue: Vec::new(), red: Vec::new(), violet: Vec::new()};
|
let mut bbc = lib::BodiesByCoalition {
|
||||||
|
blue: Vec::new(),
|
||||||
|
red: Vec::new(),
|
||||||
|
violet: Vec::new(),
|
||||||
|
};
|
||||||
let mut continued = false;
|
let mut continued = false;
|
||||||
let mut line_type: u8 = UNKNOWN;
|
let mut line_type = LineType::Unknown;
|
||||||
let mut ids = lib::IDs{blue: Vec::new(), red: Vec::new(), violet: Vec::new(), unknown: Vec::new()};
|
let mut coalitions = lib::IDs {
|
||||||
|
blue: HashSet::new(),
|
||||||
|
red: HashSet::new(),
|
||||||
|
violet: HashSet::new(),
|
||||||
|
unknown: HashSet::new(),
|
||||||
|
};
|
||||||
for line in body {
|
for line in body {
|
||||||
let result = process_line(continued, &mut ids, line, line_type);
|
let result = process_line(continued, &mut coalitions, line, line_type);
|
||||||
line_type = result.0;
|
line_type = result.0;
|
||||||
continued = result.1;
|
continued = result.1;
|
||||||
let id = result.2;
|
let id = result.2;
|
||||||
if line_type == TIMESTAMP {
|
if line_type == LineType::Timestamp {
|
||||||
bbc.blue.push(line);
|
bbc.blue.push(line);
|
||||||
bbc.red.push(line);
|
bbc.red.push(line);
|
||||||
bbc.violet.push(line);
|
bbc.violet.push(line);
|
||||||
} else { // destruction or telemetry
|
} else {
|
||||||
if ids.blue.contains(&id) {
|
// destruction or telemetry
|
||||||
|
if coalitions.blue.contains(&id) {
|
||||||
bbc.blue.push(line);
|
bbc.blue.push(line);
|
||||||
} else if ids.red.contains(&id) {
|
} else if coalitions.red.contains(&id) {
|
||||||
bbc.red.push(line);
|
bbc.red.push(line);
|
||||||
} else if ids.violet.contains(&id) {
|
} else if coalitions.violet.contains(&id) {
|
||||||
bbc.violet.push(line);
|
bbc.violet.push(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,63 +84,111 @@ fn divide_body_by_coalition(body: &Vec<String>) -> lib::BodiesByCoalition {
|
|||||||
bbc
|
bbc
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_line<'a>(continued: bool, ids: &mut lib::IDs<'a>, line: &'a String, last_line_type: u8) -> (u8, bool, &'a str) {
|
fn process_line<'a>(
|
||||||
let mut id = "both";
|
continued: bool,
|
||||||
|
coalitions: &mut lib::IDs<'a>,
|
||||||
|
line: &'a str,
|
||||||
|
last_line_type: LineType,
|
||||||
|
) -> (LineType, bool, &'a str) {
|
||||||
|
let mut id = "";
|
||||||
let line_type;
|
let line_type;
|
||||||
let will_continue: bool;
|
|
||||||
if !continued {
|
if !continued {
|
||||||
let first_char = line.chars().nth(0).expect("malformed line");
|
line_type = determine_line_type(line);
|
||||||
if first_char == COMMENT {
|
if line_type == LineType::Telemetry {
|
||||||
line_type = TIMESTAMP;
|
id = get_id_from_line(line);
|
||||||
} else if first_char == MINUS {
|
assign_id_to_coalitions(coalitions, line, id)
|
||||||
line_type = DESTRUCTION;
|
|
||||||
} else {
|
|
||||||
line_type = TELEMETRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if line_type == TELEMETRY {
|
|
||||||
id = line
|
|
||||||
.split_once(',') // TODO catch the None
|
|
||||||
.unwrap()
|
|
||||||
.0;
|
|
||||||
//let id_str = id.to_string();
|
|
||||||
if line.contains("Color=") {
|
|
||||||
if line.contains("Color=Blue") {
|
|
||||||
ids.blue.push(id);
|
|
||||||
} else if line.contains("Color=Red") {
|
|
||||||
ids.red.push(id);
|
|
||||||
} else if line.contains("Color=Violet") {
|
|
||||||
ids.violet.push(id);
|
|
||||||
} else {
|
|
||||||
ids.unknown.push(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
line_type = last_line_type;
|
line_type = last_line_type;
|
||||||
}
|
}
|
||||||
if line.ends_with("\\") {
|
let line_will_continue = will_line_continue(line);
|
||||||
will_continue = true;
|
(line_type, line_will_continue, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn will_line_continue(line: &str) -> bool {
|
||||||
|
line.ends_with('\\')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_id_from_line(line: &str) -> &str {
|
||||||
|
let result = line.split_once(',');
|
||||||
|
let split = match result {
|
||||||
|
Some(t) => t,
|
||||||
|
None => panic!("Could not get ID from line!"),
|
||||||
|
};
|
||||||
|
split.0 as _
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_id_to_coalitions<'a>(coalitions: &mut lib::IDs<'a>, line: &'a str, id: &'a str) {
|
||||||
|
if line.contains("Color=") {
|
||||||
|
if line.contains("Color=Blue") {
|
||||||
|
coalitions.blue.insert(id);
|
||||||
|
} else if line.contains("Color=Red") {
|
||||||
|
coalitions.red.insert(id);
|
||||||
|
} else if line.contains("Color=Violet") {
|
||||||
|
coalitions.violet.insert(id);
|
||||||
} else {
|
} else {
|
||||||
will_continue = false;
|
coalitions.unknown.insert(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(line_type, will_continue, id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_output_filenames(input_filename: &String) -> lib::OutputFilenames {
|
fn determine_line_type(line: &str) -> LineType {
|
||||||
let blue = input_filename.replace(".zip", "_blue.zip");
|
let first_char = line.chars().next().expect("malformed line");
|
||||||
let red = input_filename.replace(".zip", "_red.zip");
|
if first_char == COMMENT {
|
||||||
let violet = input_filename.replace(".zip", "_violet.zip");
|
LineType::Timestamp
|
||||||
|
} else if first_char == MINUS {
|
||||||
|
LineType::Destruction
|
||||||
|
} else {
|
||||||
|
LineType::Telemetry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_output_filenames(input_filename: &String, is_zip: bool) -> lib::OutputFilenames {
|
||||||
|
let output_filenames_zip: lib::FilenamesVariant;
|
||||||
|
let output_filenames_txt: lib::FilenamesVariant;
|
||||||
|
|
||||||
|
if is_zip {
|
||||||
|
output_filenames_zip =
|
||||||
|
get_output_filenames_for_extension(input_filename, EXTENSION_ZIP, EXTENSION_ZIP);
|
||||||
|
output_filenames_txt =
|
||||||
|
get_output_filenames_for_extension(input_filename, EXTENSION_ZIP, EXTENSION_TXT);
|
||||||
|
} else {
|
||||||
|
output_filenames_zip = get_output_filenames_dummy();
|
||||||
|
output_filenames_txt =
|
||||||
|
get_output_filenames_for_extension(input_filename, EXTENSION_TXT, EXTENSION_TXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
lib::OutputFilenames {
|
||||||
|
txt: output_filenames_txt,
|
||||||
|
zip: output_filenames_zip,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_output_filenames_dummy() -> lib::FilenamesVariant {
|
||||||
|
let blue = "".to_string();
|
||||||
|
let red = "".to_string();
|
||||||
|
let violet = "".to_string();
|
||||||
|
lib::FilenamesVariant { blue, red, violet }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_output_filenames_for_extension(
|
||||||
|
input_filename: &String,
|
||||||
|
old_extension: &str,
|
||||||
|
new_extension: &str,
|
||||||
|
) -> lib::FilenamesVariant {
|
||||||
|
let blue =
|
||||||
|
lib::get_output_filenames_individual(input_filename, old_extension, new_extension, "_blue");
|
||||||
|
let red =
|
||||||
|
lib::get_output_filenames_individual(input_filename, old_extension, new_extension, "_red");
|
||||||
|
let violet = lib::get_output_filenames_individual(
|
||||||
|
input_filename,
|
||||||
|
old_extension,
|
||||||
|
new_extension,
|
||||||
|
"_violet",
|
||||||
|
);
|
||||||
let output_filenames_zip = lib::FilenamesVariant { blue, red, violet };
|
let output_filenames_zip = lib::FilenamesVariant { blue, red, violet };
|
||||||
|
lib::sanity_check_output_filenames(input_filename, &output_filenames_zip);
|
||||||
// TODO make sure the replace was successful
|
output_filenames_zip
|
||||||
let blue = input_filename.replace(".txt", "_blue.txt");
|
|
||||||
let red = input_filename.replace(".txt", "_red.txt");
|
|
||||||
let violet = input_filename.replace(".txt", "_violet.txt");
|
|
||||||
let output_filenames_txt = lib::FilenamesVariant{blue, red, violet};
|
|
||||||
|
|
||||||
let output_filenames = lib::OutputFilenames{txt: output_filenames_txt, zip: output_filenames_zip};
|
|
||||||
output_filenames
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_input_file() -> (String, bool) {
|
fn find_input_file() -> (String, bool) {
|
||||||
@@ -140,27 +202,30 @@ fn find_input_file() -> (String, bool) {
|
|||||||
} else if filename.ends_with(EXTENSION_ZIP) {
|
} else if filename.ends_with(EXTENSION_ZIP) {
|
||||||
return (filename, true);
|
return (filename, true);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
println!("No tacview input file found in current directory.");
|
println!("No tacview input file found in current directory.");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn read_data(filename: &String, is_zip: bool) -> Vec<String> {
|
fn read_data(filename: &String, is_zip: bool) -> Vec<String> {
|
||||||
let file = fs::File::open(filename).expect("Could not read from input file");
|
let file = fs::File::open(filename).expect("Could not read from input file");
|
||||||
let buf = BufReader::new(file);
|
let buf = BufReader::new(file);
|
||||||
return if is_zip {
|
return if is_zip {
|
||||||
let mut archive = zip::ZipArchive::new(buf).expect("Could not read zip data");
|
let mut archive = zip::ZipArchive::new(buf).expect("Could not read zip data");
|
||||||
let inner_file = archive.by_index(0).unwrap();
|
let inner_file = archive
|
||||||
|
.by_index(0)
|
||||||
|
.expect("Could not read telemetry file from zip archive");
|
||||||
let inner_buf = BufReader::new(inner_file);
|
let inner_buf = BufReader::new(inner_file);
|
||||||
let lines: Vec<String> = inner_buf.lines()
|
let lines: Vec<String> = inner_buf
|
||||||
|
.lines()
|
||||||
.map(|l| l.expect("Could not parse line"))
|
.map(|l| l.expect("Could not parse line"))
|
||||||
.collect();
|
.collect();
|
||||||
lines
|
lines
|
||||||
} else {
|
} else {
|
||||||
let lines: Vec<String> = buf.lines()
|
let lines: Vec<String> = buf
|
||||||
|
.lines()
|
||||||
.map(|l| l.expect("Could not parse line"))
|
.map(|l| l.expect("Could not parse line"))
|
||||||
.collect();
|
.collect();
|
||||||
lines
|
lines
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user