use crate::videos::base_video::{BaseVideo, NewBaseVideo};
use crate::videos::byte_reader::ByteReader;
use crate::videos::types::{ErrReadVideoReason, Event, MouseEvent, VideoActionStateRecorder};
#[cfg(any(feature = "py", feature = "rs"))]
use crate::videos::NewSomeVideo;
use crate::videos::NewSomeVideo2;
use std::cmp::{max, min};
pub struct AvfVideo {
pub file_name: String,
pub data: BaseVideo<Vec<Vec<i32>>>,
}
#[cfg(any(feature = "py", feature = "rs"))]
impl NewSomeVideo<&str> for AvfVideo {
fn new(file_name: &str) -> Self {
AvfVideo {
file_name: file_name.to_string(),
data: BaseVideo::<Vec<Vec<i32>>>::new(file_name),
}
}
}
impl NewSomeVideo2<Vec<u8>, &str> for AvfVideo {
fn new(raw_data: Vec<u8>, file_name: &str) -> Self {
AvfVideo {
file_name: file_name.to_string(),
data: BaseVideo::<Vec<Vec<i32>>>::new(raw_data),
}
}
}
impl AvfVideo {
pub fn parse(&mut self) -> Result<(), ErrReadVideoReason> {
match self.data.get_u8() {
Ok(_) => {}
Err(_) => return Err(ErrReadVideoReason::FileIsEmpty),
};
self.data.offset += 4;
self.data.level = self.data.get_u8()?;
match self.data.level {
3 => {
self.data.width = 8;
self.data.height = 8;
self.data.mine_num = 10;
}
4 => {
self.data.width = 16;
self.data.height = 16;
self.data.mine_num = 40;
}
5 => {
self.data.width = 30;
self.data.height = 16;
self.data.mine_num = 99;
}
6 => {
self.data.width = self.data.get_u8()? as usize + 1;
self.data.height = self.data.get_u8()? as usize + 1;
self.data.mine_num = self.data.get_u16()? as usize;
}
_ => return Err(ErrReadVideoReason::InvalidLevel),
}
self.data.board = vec![vec![0; self.data.width]; self.data.height];
for _ in 0..self.data.mine_num {
let c = self.data.get_u8()? as usize;
let d = self.data.get_u8()? as usize;
self.data.board[c - 1][d - 1] = -1;
}
for x in 0..self.data.height {
for y in 0..self.data.width {
if self.data.board[x][y] == -1 {
for j in max(1, x) - 1..min(self.data.height, x + 2) {
for k in max(1, y) - 1..min(self.data.width, y + 2) {
if self.data.board[j][k] >= 0 {
self.data.board[j][k] += 1;
}
}
}
}
}
}
let mut t = 0;
for x in 0..self.data.width {
for y in 0..self.data.height {
let a2res = match self.data.board[y][x] {
-1 => 10,
e @ _ => e as usize + 1,
};
t += a2res * (x + x * y);
}
}
let s = t.to_string(); let mut s1 = String::new();
for c in s.chars() {
let new_char = (c as u8 - 45) as char; s1.push(new_char); }
for _ in 0..s1.to_string().len() + 4 {
self.data.get_char()?;
}
self.data.country = match self.data.get_u8()? {
8 | 37 => "CN".to_string(),
10 => "GB".to_string(), 12 => "FR".to_string(),
13 => "DE".to_string(),
23 => "KR".to_string(),
29 => "PL".to_string(),
31 => "RU".to_string(),
41 => "US".to_string(),
69 => "JP".to_string(),
_ => "XX".to_string(),
};
let mut buffer: [char; 5] = ['\0'; 5];
loop {
buffer[0] = buffer[1];
buffer[1] = buffer[2];
buffer[2] = buffer[3];
buffer[3] = buffer[4];
buffer[4] = self.data.get_char()?;
if buffer[2] == '['
&& (buffer[3] == '0' || buffer[3] == '1' || buffer[3] == '2' || buffer[3] == '3')
&& buffer[4] == '|'
{
break;
}
}
if buffer[0] as u8 == 17 {
self.data.use_question = true;
} else if buffer[0] as u8 == 127 {
self.data.use_question = false;
} else {
return Err(ErrReadVideoReason::InvalidParams);
}
if self.data.level == 6 {
loop {
if self.data.get_char()? == '|' {
break;
}
}
}
let mut start_time = String::new();
loop {
match self.data.get_char()? {
'|' => break,
other => start_time.push(other),
}
}
self.data.start_time = self.data.parse_avf_start_timestamp(&start_time)?;
let mut end_time = String::new();
let mut buffer: [char; 2];
loop {
match self.data.get_char()? {
'|' => {
buffer = ['\0', '|'];
break;
}
'B' => {
buffer = ['|', 'B'];
break;
}
other => end_time.push(other),
}
}
self.data.end_time = self.data.parse_avf_end_timestamp(&start_time, &end_time)?;
loop {
if buffer[0] == '|' && buffer[1] == 'B' {
break;
}
buffer[0] = buffer[1];
buffer[1] = self.data.get_char()?;
}
let s = self.data.get_utf8_c_string('T')?;
self.data.static_params.bbbv = match s.parse() {
Ok(v) => v,
Err(_) => return Err(ErrReadVideoReason::InvalidParams),
};
let mut s = self.data.get_utf8_c_string(']')?;
s = str::replace(&s, ",", "."); let _time_from_header = match s.parse::<f64>() {
Ok(v) => v - 1.0,
Err(_) => return Err(ErrReadVideoReason::InvalidParams),
};
let mut buffer = [0u8; 8];
while buffer[2] != 1 || buffer[1] > 1 {
buffer[0] = buffer[1];
buffer[1] = buffer[2];
buffer[2] = self.data.get_u8()?;
}
for i in 3..8 {
buffer[i] = self.data.get_u8()?;
}
loop {
self.data
.video_action_state_recorder
.push(VideoActionStateRecorder {
time: ((buffer[6] as u16) << 8 | buffer[2] as u16) as f64 - 1.0
+ (buffer[4] as f64) / 100.0,
event: Some(Event::Mouse(MouseEvent {
mouse: match buffer[0] {
1 => "mv".to_string(),
3 => "lc".to_string(),
5 => "lr".to_string(),
9 => "rc".to_string(),
17 => "rr".to_string(),
33 => "mc".to_string(),
65 => "mr".to_string(),
145 => "rr".to_string(),
193 => "mr".to_string(),
11 => panic!(),
21 => "lr".to_string(),
_ => return Err(ErrReadVideoReason::InvalidVideoEvent),
},
x: (buffer[1] as u16) << 8 | buffer[3] as u16,
y: (buffer[5] as u16) << 8 | buffer[7] as u16,
})),
..VideoActionStateRecorder::default()
});
for i in 0..8 {
buffer[i] = self.data.get_u8()?;
}
if buffer[2] == 0 && buffer[6] == 0 {
break;
}
}
if let Some(last) = self.data.video_action_state_recorder.last() {
if _time_from_header + 1e-6 < last.time {
let last_time = last.time;
let mut lr_time = 0.0;
for record in self.data.video_action_state_recorder.iter_mut().rev() {
if let Some(Event::Mouse(mouse_event)) = &record.event {
if mouse_event.mouse == "lr" {
lr_time = record.time;
}
}
}
self.data.set_rtime(last_time - lr_time).unwrap();
} else {
self.data.set_rtime(_time_from_header).unwrap();
}
}
while self.data.get_char()? != 'S' {}
while self.data.get_char()? != 'k' {}
while self.data.get_char()? != 'i' {}
while self.data.get_char()? != 'n' {}
while self.data.get_char()? != ':' {}
while self.data.get_char()? != '\r' {}
self.data.player_identifier = self.data.get_unknown_encoding_c_string('\r')?;
self.data.software = "Arbiter".to_string();
self.data.can_analyse = true;
Ok(())
}
}