-
Notifications
You must be signed in to change notification settings - Fork 0
/
BuildMeetsGraph.fsx
129 lines (96 loc) · 3.55 KB
/
BuildMeetsGraph.fsx
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
#r "nuget: FSharp.Data"
#r "nuget: fsharp.fgl"
#r "nuget: FSharp.FGL.ArrayAdjacencyGraph"
open System
open System.IO
open FSharp.Data
open FSharp.FGL
open FSharp.FGL.ArrayAdjacencyGraph
let path = "C:/Users/harry/SlackNetwork/GoogleExport"
let root = DirectoryInfo path
type MeetEvent = {
Date : DateTime
MeetingCode : string
Event : string
Actor : string
Duration : float
}
type Attendence = {
Name : string
Duration : (DateTime * DateTime)
}
type Meet = {
Start : DateTime
End : DateTime option
Participants: Attendence list
MeetId : string
}
let file = Path.Combine(root.FullName, "MeetsExport.csv")
let rows = CsvFile.Load(file)
let parseFile file =
let meets : Meet list = []
rows.Rows
|> Seq.map(fun r ->
{
Date = DateTime.Parse((r.GetColumn "Date"));
MeetingCode = (r.GetColumn "Meeting code");
Event = (r.GetColumn "Event");
Actor = (r.GetColumn "Actor");
Duration = float (r.GetColumn"Duration (seconds)")
}
)
|> Seq.filter(fun me -> not (String.IsNullOrEmpty(me.Actor)))
|> Seq.sortBy(fun me -> me.Date)
|> Seq.fold(fun (meetList: Meet list) (me: MeetEvent) ->
match me.Event with
| "Presentation started" ->
meetList
|> List.map(fun m -> if m.MeetId = me.MeetingCode && m.End.IsNone then {m with End = Some me.Date } else m )
|> List.append([{Start = me.Date; End = None; Participants = []; MeetId = me.MeetingCode}])
| "Presentation stopped" ->
meetList
|> List.map(fun m -> if m.MeetId = me.MeetingCode && m.End.IsNone then {m with End = Some me.Date } else m )
| "Endpoint left" ->
meetList
|> List.map(fun m ->
if m.MeetId = me.MeetingCode && m.End.IsNone
then {m with Participants = m.Participants |> List.append ([{Name = me.Actor; Duration = ((me.Date.AddSeconds(0.0 - me.Duration), me.Date ))}]) }
else m )
| "Knocking accepted" | "Recording activity" | "Whiteboard started" | "Invitation sent" -> meetList
| _ ->
printfn "unknown event: %A" me
failwith "unknown event"
) meets
let parsedMeets = parseFile file
let rec combinations acc size set = seq {
match size, set with
| n, x::xs ->
if n > 0 then yield! combinations (x::acc) (n - 1) xs
if n >= 0 then yield! combinations acc n xs
| 0, [] -> yield acc
| _, [] -> () }
let getEdges() =
parsedMeets
|> List.map(fun m -> combinations [] 2 m.Participants )
|> Seq.concat
|> Seq.map(fun al ->
let earliestEndDdate = (al |> List.minBy(fun a -> snd a.Duration)).Duration |> snd
let latestStartDate = (al |> List.maxBy(fun a -> fst a.Duration)).Duration |> fst
let delta = (earliestEndDdate - latestStartDate).TotalSeconds
let weight = if delta > 0 then delta else 0
al[0].Name, al[1].Name, weight
)
|> Seq.groupBy(fun (f,t,w ) -> f,t )
|> Seq.map(fun e -> e, (snd e) |> Seq.sumBy(fun (f,t,w)-> w) )
|> Seq.map(fun (e,w) -> (fst e) , w)
|> Seq.map(fun (e, w) -> (fst e), (snd e), w)
|> Seq.toList
let buildGraph() =
let edges = getEdges()
let nodes =
edges
|> List.map(fun (f,t,w) -> f)
|> List.append(edges |> List.map(fun (f,t,w) -> t))
|> List.map(fun n -> n, n)
|> List.distinct
ArrayAdjacencyGraph(nodes, edges)