diff --git a/src/routes.rs b/src/routes.rs index 18d54c5..d55aac9 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -28,9 +28,9 @@ pub async fn skip_segments( let hc = hash.clone(); - let cat: Vec = serde_json::from_str(categories.unwrap_or("[]")).unwrap(); + let cat: Vec = serde_json::from_str(categories.unwrap_or("[\"sponsor\"]")).unwrap(); - if cat.is_empty() && categories.is_some() { + if cat.is_empty() { return content::RawJson( "[]".to_string(), ); @@ -62,26 +62,51 @@ pub async fn skip_segments( // Create map of Sponsors - Hash, Sponsor let mut sponsors: HashMap = HashMap::new(); - for result in results { + for result in &results { let sponsor = { sponsors.entry(result.hashed_video_id.clone()).or_insert(Sponsor { - hash: result.hashed_video_id, - video_id: result.video_id, + hash: result.hashed_video_id.clone(), + video_id: result.video_id.clone(), segments: Vec::new(), }) }; - sponsor.segments.push(Segment { - uuid: result.uuid, - action_type: result.action_type, - category: result.category, - description: result.description, + let segment = Segment { + uuid: result.uuid.clone(), + action_type: result.action_type.clone(), + category: result.category.clone(), + description: result.description.clone(), locked: result.locked, segment: vec![result.start_time, result.end_time], - user_id: result.user_id, + user_id: result.user_id.clone(), video_duration: result.video_duration, votes: result.votes, - }); + }; + + let hash = result.hashed_video_id.clone(); + + let mut found_similar = false; + + for seg in &sponsor.segments { + if is_overlap(&segment, &seg.category, seg.segment[0], seg.segment[1]) { + found_similar = true; + break; + } + } + + if found_similar { + continue; + } + + let mut similar_segments = similar_segments(&segment, &hash, &results); + similar_segments.push(segment.clone()); + + let best_segment = best_segment(&similar_segments); + + // Add if not already in sponsor + if !sponsor.segments.contains(&best_segment) { + sponsor.segments.push(best_segment); + } } if !sponsors.is_empty() { @@ -102,3 +127,62 @@ pub async fn skip_segments( return content::RawJson(resp); } + +fn similar_segments(segment: &Segment, hash: &str, segments: &Vec) -> Vec { + let mut similar_segments: Vec = Vec::new(); + + for seg in segments { + if seg.uuid == segment.uuid { + continue; + } + + if seg.hashed_video_id != hash { + continue; + } + + let is_similar = is_overlap(segment, &seg.category, seg.start_time, seg.end_time); + + if is_similar { + similar_segments.push(Segment { + uuid: seg.uuid.clone(), + action_type: seg.action_type.clone(), + category: seg.category.clone(), + description: seg.description.clone(), + locked: seg.locked, + segment: vec![seg.start_time, seg.end_time], + user_id: seg.user_id.clone(), + video_duration: seg.video_duration, + votes: seg.votes, + }); + } + } + + similar_segments +} + +fn is_overlap(seg: &Segment, cat: &str, start: f32, end: f32) -> bool { + if seg.category != cat { + return false; + } + + if seg.segment[0] > start && seg.segment[1] < end { + return true; + } + let overlap = f32::min(seg.segment[1], end) - f32::max(seg.segment[0], start); + let duration = f32::max(seg.segment[1], end) - f32::min(seg.segment[0], start); + overlap / duration > 0.1 +} + +fn best_segment(segments: &Vec) -> Segment { + let mut best_segment = segments[0].clone(); + let mut best_votes = segments[0].votes; + + for segment in segments { + if segment.votes > best_votes { + best_segment = segment.clone(); + best_votes = segment.votes; + } + } + + best_segment +} \ No newline at end of file diff --git a/src/structs.rs b/src/structs.rs index b013e83..b155498 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct Sponsor { pub hash: String, #[serde(rename = "videoID")] @@ -8,7 +8,7 @@ pub struct Sponsor { pub segments: Vec, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct Segment { #[serde(rename = "UUID")] pub uuid: String, @@ -24,3 +24,9 @@ pub struct Segment { pub video_duration: f32, pub votes: i32, } + +impl PartialEq for Segment { + fn eq(&self, other: &Self) -> bool { + self.uuid == other.uuid + } +}