1- use chrono:: { DateTime , Datelike , Days , TimeDelta , Utc } ;
1+ use chrono:: { DateTime , Datelike , TimeDelta , Utc } ;
22use fake:: Fake ;
33use rand:: seq:: SliceRandom ;
44use rand:: Rng ;
55use serde:: Serialize ;
66
7- use crate :: users:: User ;
8- use crate :: videos:: Video ;
9-
107#[ derive( Debug , Clone , Serialize ) ]
118pub struct Interaction {
129 pub interaction_id : u32 ,
@@ -18,8 +15,6 @@ pub struct Interaction {
1815 #[ serde( serialize_with = "serialize_timestamp" ) ]
1916 pub interaction_date : DateTime < Utc > ,
2017 #[ serde( serialize_with = "serialize_timestamp" ) ]
21- pub previous_interaction_date : DateTime < Utc > ,
22- #[ serde( serialize_with = "serialize_timestamp" ) ]
2318 pub interaction_month : DateTime < Utc > ,
2419}
2520
@@ -30,12 +25,95 @@ where
3025 serializer. serialize_str ( & date. format ( "%Y-%m-%d %H:%M:%S" ) . to_string ( ) )
3126}
3227
33- impl Interaction {
34- pub fn generate ( num : u32 , users : Vec < User > , videos : Vec < Video > ) -> Vec < Interaction > {
35- let mut now = Utc :: now ( ) ;
28+ #[ derive( Debug , Clone ) ]
29+ pub struct InteractionGenerator {
30+ max_users : u32 ,
31+ max_videos : u32 ,
32+ max_interactions : u32 ,
33+ interaction_id : u32 ,
34+ start : chrono:: DateTime < Utc > ,
35+ }
36+
37+ impl Default for InteractionGenerator {
38+ fn default ( ) -> Self {
39+ Self {
40+ max_users : 1_000 ,
41+ max_videos : 1_000 ,
42+ max_interactions : 10_000_000 ,
43+ interaction_id : 0 ,
44+ start : Utc :: now ( ) ,
45+ }
46+ }
47+ }
48+
49+ impl InteractionGenerator {
50+ pub fn max_users ( mut self , n : u32 ) -> Self {
51+ self . max_users = n;
52+ self
53+ }
54+
55+ pub fn max_videos ( mut self , n : u32 ) -> Self {
56+ self . max_videos = n;
57+ self
58+ }
59+
60+ pub fn max_interactions ( mut self , n : u32 ) -> Self {
61+ self . max_interactions = n;
62+ self
63+ }
64+
65+ pub fn start_date ( mut self , start : DateTime < Utc > ) -> Self {
66+ self . start = start;
67+ self
68+ }
69+
70+ pub fn generate ( mut self ) -> Vec < Interaction > {
3671 let mut rng = rand:: thread_rng ( ) ;
3772
38- let mut interactions = Vec :: with_capacity ( num as usize ) ;
73+ let mut interactions = Vec :: with_capacity ( self . max_interactions as usize ) ;
74+
75+ for _ in 0 ..self . max_interactions {
76+ let random_delay = chrono:: TimeDelta :: seconds ( rng. gen_range ( 0 ..600 ) ) ;
77+ let interaction_date = self . timestamp_generator ( ) - random_delay;
78+
79+ let interaction = Interaction {
80+ interaction_id : self . interaction_id_generator ( ) ,
81+ user_id : self . user_id_generator ( & mut rng) ,
82+ video_id : self . video_id_generator ( & mut rng) ,
83+ category_id : self . video_category_generator ( & mut rng) ,
84+ interaction_type : self . interaction_type_generator ( & mut rng) ,
85+ watch_time : self . watch_time_generator ( & mut rng) ,
86+ interaction_month : interaction_date. with_day ( 1 ) . unwrap ( ) ,
87+ interaction_date,
88+ } ;
89+
90+ interactions. push ( interaction) ;
91+ }
92+
93+ interactions
94+ }
95+ }
96+
97+ impl InteractionGenerator {
98+ fn interaction_id_generator ( & mut self ) -> u32 {
99+ if self . interaction_id == self . max_interactions {
100+ self . interaction_id = 0 ;
101+ } else {
102+ self . interaction_id += 1 ;
103+ }
104+
105+ self . interaction_id
106+ }
107+
108+ fn user_id_generator ( & self , rng : & mut impl Rng ) -> u32 {
109+ Fake :: fake_with_rng ( & ( 0 ..self . max_videos ) , rng)
110+ }
111+
112+ fn video_id_generator ( & self , rng : & mut impl Rng ) -> u32 {
113+ Fake :: fake_with_rng ( & ( 0 ..self . max_videos ) , rng)
114+ }
115+
116+ fn interaction_type_generator ( & self , rng : & mut impl Rng ) -> String {
39117 let interaction_types = [
40118 ( "like" , 1.5 ) ,
41119 ( "dislike" , 0.2 ) ,
@@ -45,44 +123,24 @@ impl Interaction {
45123 ( "skip" , 10.0 ) ,
46124 ] ;
47125
48- for _ in 0 ..num {
49- let user = users. choose ( & mut rng) . unwrap ( ) ;
50- let video = videos. choose ( & mut rng) . unwrap ( ) ;
51-
52- let random_delay = chrono:: TimeDelta :: seconds ( rng. gen_range ( 0 ..600 ) ) ;
53- let interaction_date = now + random_delay;
54-
55- let previous_interaction_date = interaction_date - Days :: new ( rng. gen_range ( 0 ..90 ) ) ;
56-
57- let mut watch_time = rng. gen_range ( 1 ..video. video_length ) ;
58-
59- let probability_watched_till_end = 1.0 - ( ( watch_time / video. video_length ) as f64 ) ;
60-
61- let watched_till_end = rng. gen_bool ( probability_watched_till_end) ;
126+ interaction_types
127+ . choose_weighted ( rng, |item| item. 1 )
128+ . unwrap ( )
129+ . 0
130+ . to_string ( )
131+ }
62132
63- if watched_till_end {
64- watch_time = video . video_length ;
65- }
133+ fn video_category_generator ( & self , rng : & mut impl Rng ) -> u8 {
134+ Fake :: fake_with_rng ( & ( 1 ..= 11 ) , rng )
135+ }
66136
67- interactions. push ( Interaction {
68- interaction_id : Fake :: fake_with_rng ( & ( 100_000_000 ..999_999_999 ) , & mut rng) ,
69- user_id : user. user_id ,
70- video_id : video. video_id ,
71- category_id : video. category_id ,
72- interaction_type : interaction_types
73- . choose_weighted ( & mut rng, |item| item. 1 )
74- . unwrap ( )
75- . 0
76- . to_string ( ) ,
77- watch_time,
78- interaction_date,
79- previous_interaction_date,
80- interaction_month : interaction_date. with_day ( 1 ) . unwrap ( ) ,
81- } ) ;
137+ fn watch_time_generator ( & self , rng : & mut impl Rng ) -> u8 {
138+ Fake :: fake_with_rng ( & ( 10 ..=250 ) , rng)
139+ }
82140
83- now += TimeDelta :: seconds ( 1 ) ;
84- }
141+ fn timestamp_generator ( & mut self ) -> DateTime < Utc > {
142+ self . start += TimeDelta :: seconds ( 1 ) ;
85143
86- interactions
144+ self . start
87145 }
88146}
0 commit comments