diff --git a/Semester-4/Homework-5/Network.Tests/LogBFS.fs b/Semester-4/Homework-5/Network.Tests/LogBFS.fs
new file mode 100644
index 0000000..c702ff7
--- /dev/null
+++ b/Semester-4/Homework-5/Network.Tests/LogBFS.fs
@@ -0,0 +1,25 @@
+namespace Network
+
+/// Logger for computers with 100% infection chance
+type LogBFS() =
+ let mutable stepNumber = 0
+ let mutable isSomeoneHealthy = true
+ let mutable isBFS = true
+
+ member this.IsSomeoneHealthy = isSomeoneHealthy
+ member this.IsBFS = isBFS
+
+ interface ILog with
+ member this.LogState state =
+
+ if (state.[2 - stepNumber] = false || state.[2 + stepNumber] = false) then
+ isBFS <- false
+
+ if stepNumber >= 500 then
+ failwith "Simulation was not stopped, but probability is 1!"
+ else
+ isSomeoneHealthy <- Array.contains false <| state
+ stepNumber <- stepNumber + 1
+
+
+ stepNumber
\ No newline at end of file
diff --git a/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs b/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs
new file mode 100644
index 0000000..7b3d3f0
--- /dev/null
+++ b/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs
@@ -0,0 +1,11 @@
+namespace Network
+
+/// Logger for network of uninfectable computers
+type LogZeroChance() =
+ let mutable stepNumber = 0
+
+ interface ILog with
+ member this.LogState state =
+
+ stepNumber <- stepNumber + 1
+ stepNumber
\ No newline at end of file
diff --git a/Semester-4/Homework-5/Network.Tests/Network.Tests.fsproj b/Semester-4/Homework-5/Network.Tests/Network.Tests.fsproj
new file mode 100644
index 0000000..6e4a2bc
--- /dev/null
+++ b/Semester-4/Homework-5/Network.Tests/Network.Tests.fsproj
@@ -0,0 +1,27 @@
+
+
+
+ netcoreapp3.1
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Semester-4/Homework-5/Network.Tests/UnitTests.fs b/Semester-4/Homework-5/Network.Tests/UnitTests.fs
new file mode 100644
index 0000000..59b3217
--- /dev/null
+++ b/Semester-4/Homework-5/Network.Tests/UnitTests.fs
@@ -0,0 +1,64 @@
+namespace Network
+
+module Tests =
+ open NUnit.Framework
+ open FsUnit
+
+ []
+ let ``Simulator should work correctly with overall chance = 1`` () =
+ let computers = [| for i in 1..6 -> ({new IOperatingSystem with
+ member this.InfectionChance = 1.0}) |]
+ let graph =
+ [|
+ [1]
+ [0; 2]
+ [3; 1]
+ [2; 4; 5]
+ [3; 5]
+ [3; 4]
+ |]
+
+ let logger = new LogBFS()
+ let simulator = new Simulator(computers, graph, logger)
+ simulator.Start [|false; false; true; false; false; false|] |> ignore
+
+ logger.IsSomeoneHealthy |> should be False
+
+ []
+ let ``Simulator should work correctly with overall chance = 0`` () =
+ let computers = [| for i in 1..6 -> ({new IOperatingSystem with
+ member this.InfectionChance = 0.0}) |]
+ let graph =
+ [|
+ [1]
+ [0; 2]
+ [1; 3]
+ [2; 4; 5]
+ [3; 5]
+ [3; 4]
+ |]
+ let expectedState = Array.concat[ [|true|]; [| for i in 1..5 -> false |] ]
+ let log = new LogZeroChance()
+
+ let simulator = new Simulator(computers, graph, log)
+ let resultingNetwork = simulator.Start(expectedState)
+ resultingNetwork |> should equal expectedState
+
+ []
+ let ``Infection should work like BFS with infection chance == 1`` () =
+ let computers = [| for i in 1..6 -> ({new IOperatingSystem with
+ member this.InfectionChance = 1.0}) |]
+ let graph =
+ [|
+ [1]
+ [0; 2]
+ [1; 3]
+ [2; 4]
+ [3]
+ |]
+
+ let logger = new LogBFS()
+ let simulator = new Simulator(computers, graph, logger)
+ simulator.Start [|false; false; true; false; false|] |> ignore
+
+ logger.IsBFS |> should be True
diff --git a/Semester-4/Homework-5/Network/Log/ConsoleLog.fs b/Semester-4/Homework-5/Network/Log/ConsoleLog.fs
new file mode 100644
index 0000000..6485f5b
--- /dev/null
+++ b/Semester-4/Homework-5/Network/Log/ConsoleLog.fs
@@ -0,0 +1,17 @@
+namespace Network
+
+/// Network state logger
+type ConsoleLog() =
+ let mutable step = 0
+
+ interface ILog with
+ /// Prints current network state
+ member this.LogState state =
+ printfn "Step №%d. " step
+ state |> Array.iteri (fun i item ->
+ match item with
+ | true -> printfn "Computer #%d: Infected" i
+ | false -> printfn "Computer #%d: Healthy" i)
+
+ step <- step + 1
+ step
\ No newline at end of file
diff --git a/Semester-4/Homework-5/Network/Log/ILog.fs b/Semester-4/Homework-5/Network/Log/ILog.fs
new file mode 100644
index 0000000..c269570
--- /dev/null
+++ b/Semester-4/Homework-5/Network/Log/ILog.fs
@@ -0,0 +1,6 @@
+namespace Network
+
+/// Network state logger interface
+type ILog =
+ /// Prints current network state
+ abstract member LogState : bool array -> int
\ No newline at end of file
diff --git a/Semester-4/Homework-5/Network/Network.fsproj b/Semester-4/Homework-5/Network/Network.fsproj
new file mode 100644
index 0000000..075f49f
--- /dev/null
+++ b/Semester-4/Homework-5/Network/Network.fsproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Semester-4/Homework-5/Network/Network.sln b/Semester-4/Homework-5/Network/Network.sln
new file mode 100644
index 0000000..121138b
--- /dev/null
+++ b/Semester-4/Homework-5/Network/Network.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29613.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Network", "Network.fsproj", "{608891F1-5F7C-4773-95FF-9563686EDE0C}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Network.Tests", "..\Network.Tests\Network.Tests.fsproj", "{8C57BEC3-20B6-4158-BDD8-B2454D45DA76}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {608891F1-5F7C-4773-95FF-9563686EDE0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {608891F1-5F7C-4773-95FF-9563686EDE0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {608891F1-5F7C-4773-95FF-9563686EDE0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {608891F1-5F7C-4773-95FF-9563686EDE0C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C57BEC3-20B6-4158-BDD8-B2454D45DA76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C57BEC3-20B6-4158-BDD8-B2454D45DA76}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8C57BEC3-20B6-4158-BDD8-B2454D45DA76}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8C57BEC3-20B6-4158-BDD8-B2454D45DA76}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {6055F841-A110-4496-B204-4862CD75557F}
+ EndGlobalSection
+EndGlobal
diff --git a/Semester-4/Homework-5/Network/OperatingSystem/IOperatingSystem.fs b/Semester-4/Homework-5/Network/OperatingSystem/IOperatingSystem.fs
new file mode 100644
index 0000000..79f2b2b
--- /dev/null
+++ b/Semester-4/Homework-5/Network/OperatingSystem/IOperatingSystem.fs
@@ -0,0 +1,6 @@
+namespace Network
+
+/// Describes the operating system interface
+type IOperatingSystem =
+ /// Chance of the computer getting infected
+ abstract member InfectionChance : float
\ No newline at end of file
diff --git a/Semester-4/Homework-5/Network/Program.fs b/Semester-4/Homework-5/Network/Program.fs
new file mode 100644
index 0000000..eb69c0d
--- /dev/null
+++ b/Semester-4/Homework-5/Network/Program.fs
@@ -0,0 +1,20 @@
+namespace Network
+
+module Main =
+ open System
+
+ let computers = [| for i in 1..5 -> ( {new IOperatingSystem with
+ member this.InfectionChance = 1.0}) |]
+ let graph =
+ [|
+ [1]
+ [0; 2]
+ [1; 3]
+ [2; 4]
+ [3]
+ |]
+
+ let logger = new ConsoleLog()
+ let simulator = new Simulator(computers, graph, logger)
+
+ simulator.Start [|true; false; true; false; true|] |> ignore
\ No newline at end of file
diff --git a/Semester-4/Homework-5/Network/Simulation.fs b/Semester-4/Homework-5/Network/Simulation.fs
new file mode 100644
index 0000000..9f47831
--- /dev/null
+++ b/Semester-4/Homework-5/Network/Simulation.fs
@@ -0,0 +1,56 @@
+namespace Network
+
+/// Simulates network infection process
+type Simulator(
+ computers : IOperatingSystem array,
+ graph : int list array,
+ log : ILog) =
+
+ let random = System.Random()
+
+
+ /// Starts the simulation
+ member this.Start (startState : bool array) =
+
+ /// Carries out the simulation steps
+ let rec nextStep (handlingQueue : int list) (used : bool array) (newQueue : int list) =
+ match handlingQueue with
+
+ /// Computer gets infected
+ | head :: tail when
+ not used.[head] &&
+ (random.NextDouble() < computers.[head].InfectionChance) ->
+ used.[head] <- true
+ nextStep tail used (newQueue @ graph.[head])
+
+ /// Computer does not get infected
+ /// Keeps trying to infect it
+ | head :: tail when not used.[head] ->
+
+ /// If the computer is invincible...
+ if (computers.[head].InfectionChance = 0.0) then
+ /// ...there's no need in trying to infect it
+ nextStep tail used newQueue
+ else
+ nextStep tail used (newQueue @ [head])
+
+ /// Already infected computer
+ | head :: tail ->
+ nextStep tail used newQueue
+
+ /// Empty queue
+ | [] ->
+ (newQueue, used)
+
+ /// Launches the virus into the network
+ let rec virusJump queue states =
+ match queue with
+ | [] -> states
+ | virusQueue ->
+ states |> log.LogState |> ignore
+ let newNetwork = nextStep virusQueue states List.Empty
+ virusJump (fst newNetwork) (snd newNetwork)
+
+ let infected = startState |> Array.indexed |> Array.filter (fun (i, x) -> x = true)
+ |> Array.map (fun (i, x) -> graph.[i]) |> List.concat
+ virusJump infected startState
\ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
index 8be6cd1..e1da346 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -15,6 +15,7 @@ environment:
- solution_name: Semester-4/Homework-4/BracketSeq/BracketSeq.sln
- solution_name: Semester-4/Homework-4/PointFree/PointFree.sln
- solution_name: Semester-4/Homework-4/Phonebook/Phonebook.sln
+ - solution_name: Semester-4/Homework-5/Network/Network.sln
- solution_name: Semester-4/Homework-6/Workflows/Workflows.sln
before_build: