From fc92c828538d4359cb951248cca3896a9c05e89d Mon Sep 17 00:00:00 2001 From: Timur Zinnatulin Date: Fri, 5 Jun 2020 00:15:32 +0300 Subject: [PATCH 1/5] Created network simulation. --- .../Homework-5/Network/Log/ConsoleLog.fs | 24 ++++++++ Semester-4/Homework-5/Network/Log/ILog.fs | 6 ++ Semester-4/Homework-5/Network/Network.fsproj | 17 ++++++ Semester-4/Homework-5/Network/Network.sln | 25 +++++++++ .../OperationSystem/IOperatingSystem.fs | 6 ++ .../Network/OperationSystem/Linux.fs | 7 +++ .../Network/OperationSystem/Windows.fs | 7 +++ Semester-4/Homework-5/Network/Simulation.fs | 55 +++++++++++++++++++ 8 files changed, 147 insertions(+) create mode 100644 Semester-4/Homework-5/Network/Log/ConsoleLog.fs create mode 100644 Semester-4/Homework-5/Network/Log/ILog.fs create mode 100644 Semester-4/Homework-5/Network/Network.fsproj create mode 100644 Semester-4/Homework-5/Network/Network.sln create mode 100644 Semester-4/Homework-5/Network/OperationSystem/IOperatingSystem.fs create mode 100644 Semester-4/Homework-5/Network/OperationSystem/Linux.fs create mode 100644 Semester-4/Homework-5/Network/OperationSystem/Windows.fs create mode 100644 Semester-4/Homework-5/Network/Simulation.fs 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..a9dac01 --- /dev/null +++ b/Semester-4/Homework-5/Network/Log/ConsoleLog.fs @@ -0,0 +1,24 @@ +namespace Network + +/// Network state logger +type ConsoleLog() = + let mutable step = 0 + + interface ILog with + /// Prints current network state + member this.LogState state = + let rec printList number list = + match list with + | [] -> printf "\n" + | head :: tail -> + match head with + | true -> printfn "Computer №%d: Infected" number + | false -> printfn "Computer №%d: Healthy" number + + printList (number + 1) tail + + printfn "Step №%d. " step + printList 1 (state |> List.ofArray) + + 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..1983d49 --- /dev/null +++ b/Semester-4/Homework-5/Network/Network.fsproj @@ -0,0 +1,17 @@ + + + + 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..b5704eb --- /dev/null +++ b/Semester-4/Homework-5/Network/Network.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Network", "Network.fsproj", "{608891F1-5F7C-4773-95FF-9563686EDE0C}" +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 + 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/OperationSystem/IOperatingSystem.fs b/Semester-4/Homework-5/Network/OperationSystem/IOperatingSystem.fs new file mode 100644 index 0000000..a771934 --- /dev/null +++ b/Semester-4/Homework-5/Network/OperationSystem/IOperatingSystem.fs @@ -0,0 +1,6 @@ +namespace Network + +/// Describes the operating system interface +type IOperatingSystem = + abstract member Name : string + abstract member InfectionChance : float \ No newline at end of file diff --git a/Semester-4/Homework-5/Network/OperationSystem/Linux.fs b/Semester-4/Homework-5/Network/OperationSystem/Linux.fs new file mode 100644 index 0000000..392a5a5 --- /dev/null +++ b/Semester-4/Homework-5/Network/OperationSystem/Linux.fs @@ -0,0 +1,7 @@ +namespace Network + +/// Linux OS +type Linux() = + interface IOperatingSystem with + member this.Name = "Linux" + member this.InfectionChance = 0.3 \ No newline at end of file diff --git a/Semester-4/Homework-5/Network/OperationSystem/Windows.fs b/Semester-4/Homework-5/Network/OperationSystem/Windows.fs new file mode 100644 index 0000000..ef80307 --- /dev/null +++ b/Semester-4/Homework-5/Network/OperationSystem/Windows.fs @@ -0,0 +1,7 @@ +namespace Network + +/// Windows OS +type Windows() = + interface IOperatingSystem with + member this.Name = "Windows" + member this.InfectionChance = 0.8 \ 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..6457b60 --- /dev/null +++ b/Semester-4/Homework-5/Network/Simulation.fs @@ -0,0 +1,55 @@ +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 () = + + /// Carries out the simulation steps + let rec nextStep (handlingQueue : int list) (used : bool array) = + match handlingQueue with + + /// Computer gets infected + | head :: tail when + not used.[head] && + (random.NextDouble() < computers.[head].InfectionChance) -> + used.[head] <- true + used |> log.LogState |> ignore + + nextStep (handlingQueue @ graph.[head]) used + + /// Computer does not get infected + /// Keeps trying to infect it + | head :: tail when not used.[head] -> + used |> log.LogState |> ignore + nextStep (handlingQueue @ [head]) used + + /// Already infected computer + | head :: tail -> + nextStep tail used + + /// Empty queue + | [] -> used + + /// Launches the virus into the network + let rec virusJump i (state : bool array) = + + /// All the computers are infected + if (i = computers.Length) then + true + else + match state.[i] with + | true -> virusJump (i + 1) state + | false -> + /// Tries to infect i-th computer + let newState = nextStep [i] state + virusJump (i + 1) newState + + let startingState = [| for i in 1 .. computers.Length -> false|] + + virusJump 0 startingState \ No newline at end of file From e3742bf7d957013772487b2d554fb82b3dd5a494 Mon Sep 17 00:00:00 2001 From: Timur Zinnatulin Date: Fri, 5 Jun 2020 11:45:48 +0300 Subject: [PATCH 2/5] Added main program. --- Semester-4/Homework-5/Network/Network.fsproj | 1 + Semester-4/Homework-5/Network/Program.fs | 21 ++++++++++++++++++++ Semester-4/Homework-5/Network/Simulation.fs | 1 + 3 files changed, 23 insertions(+) create mode 100644 Semester-4/Homework-5/Network/Program.fs diff --git a/Semester-4/Homework-5/Network/Network.fsproj b/Semester-4/Homework-5/Network/Network.fsproj index 1983d49..3ed6223 100644 --- a/Semester-4/Homework-5/Network/Network.fsproj +++ b/Semester-4/Homework-5/Network/Network.fsproj @@ -12,6 +12,7 @@ + diff --git a/Semester-4/Homework-5/Network/Program.fs b/Semester-4/Homework-5/Network/Program.fs new file mode 100644 index 0000000..99ef6ce --- /dev/null +++ b/Semester-4/Homework-5/Network/Program.fs @@ -0,0 +1,21 @@ +namespace Network + +module Main = + open System + + let computers = Array.concat [ [| for i in 1..3 -> (new Windows() :> IOperatingSystem) |] + ; [| for i in 1..3 -> (new Linux() :> IOperatingSystem) |] ] + let graph = + [| + [1] + [0] + [3] + [2; 4; 5] + [3; 5] + [3; 4] + |] + + let logger = new ConsoleLog() + let simulator = new Simulator(computers, graph, logger) + + simulator.Start () |> 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 index 6457b60..6ecebdf 100644 --- a/Semester-4/Homework-5/Network/Simulation.fs +++ b/Semester-4/Homework-5/Network/Simulation.fs @@ -5,6 +5,7 @@ type Simulator( computers : IOperatingSystem array, graph : int list array, log : ILog) = + let random = System.Random() /// Starts the simulation From 61d950cd2a2f96c20ecbbed8cc97887c77bdc511 Mon Sep 17 00:00:00 2001 From: Timur Zinnatulin Date: Fri, 5 Jun 2020 12:11:01 +0300 Subject: [PATCH 3/5] Added unit tests for simulation. --- Semester-4/Homework-5/Network.Tests/BadOS.fs | 6 ++ Semester-4/Homework-5/Network.Tests/GoodOS.fs | 6 ++ Semester-4/Homework-5/Network.Tests/LogBFS.fs | 36 ++++++++++ .../Homework-5/Network.Tests/LogZeroChance.fs | 18 +++++ .../Network.Tests/Network.Tests.fsproj | 29 ++++++++ .../Homework-5/Network.Tests/UnitTests.fs | 67 +++++++++++++++++++ Semester-4/Homework-5/Network/Network.sln | 8 ++- Semester-4/Homework-5/Network/Program.fs | 8 +-- 8 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 Semester-4/Homework-5/Network.Tests/BadOS.fs create mode 100644 Semester-4/Homework-5/Network.Tests/GoodOS.fs create mode 100644 Semester-4/Homework-5/Network.Tests/LogBFS.fs create mode 100644 Semester-4/Homework-5/Network.Tests/LogZeroChance.fs create mode 100644 Semester-4/Homework-5/Network.Tests/Network.Tests.fsproj create mode 100644 Semester-4/Homework-5/Network.Tests/UnitTests.fs diff --git a/Semester-4/Homework-5/Network.Tests/BadOS.fs b/Semester-4/Homework-5/Network.Tests/BadOS.fs new file mode 100644 index 0000000..c614d8d --- /dev/null +++ b/Semester-4/Homework-5/Network.Tests/BadOS.fs @@ -0,0 +1,6 @@ +namespace Network + +type BadOS () = + interface IOperatingSystem with + member this.Name = "Bad" + member this.InfectionChance = 1.0 \ No newline at end of file diff --git a/Semester-4/Homework-5/Network.Tests/GoodOS.fs b/Semester-4/Homework-5/Network.Tests/GoodOS.fs new file mode 100644 index 0000000..c21430b --- /dev/null +++ b/Semester-4/Homework-5/Network.Tests/GoodOS.fs @@ -0,0 +1,6 @@ +namespace Network + +type GoodOS () = + interface IOperatingSystem with + member this.Name = "Good" + member this.InfectionChance = 0.0 \ No newline at end of file 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..b0e564c --- /dev/null +++ b/Semester-4/Homework-5/Network.Tests/LogBFS.fs @@ -0,0 +1,36 @@ +namespace Network + +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 = + let rec printList number list = + match list with + | [] -> printf "\n" + | head :: tail -> + match head with + | true -> printfn "Computer #%d: Infected" number + | false -> printfn "Computer #%d: Healthy" number + + printList (number + 1) tail + + printfn "Step %d: " stepNumber + printList 1 (state |> List.ofArray) + + if (state.[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..41c6d34 --- /dev/null +++ b/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs @@ -0,0 +1,18 @@ +namespace Network + +type LogZeroChance(compNumber) = + let mutable stepNumber = 0 + + interface ILog with + member this.LogState state = + if stepNumber >= 500 then + let expectedState = [| for i in 1..compNumber -> false |] + + if state = expectedState then + failwith "Test success!" + else + failwith "Test failure!" + else + 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..055e071 --- /dev/null +++ b/Semester-4/Homework-5/Network.Tests/Network.Tests.fsproj @@ -0,0 +1,29 @@ + + + + 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..65e2c01 --- /dev/null +++ b/Semester-4/Homework-5/Network.Tests/UnitTests.fs @@ -0,0 +1,67 @@ +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 BadOS() :> IOperatingSystem) |] + let graph = + [| + [1] + [0] + [3] + [2; 4; 5] + [3; 5] + [3; 4] + |] + + let logger = new LogBFS() + let simulator = new Simulator(computers, graph, logger) + simulator.Start() |> ignore + + logger.IsSomeoneHealthy() |> should be False + + [] + let ``Simulator should work correctly with overall chance = 0`` () = + let computers = [| for i in 1..6 -> (new GoodOS() :> IOperatingSystem) |] + let graph = + [| + [1] + [0] + [3] + [2; 4; 5] + [3; 5] + [3; 4] + |] + let expectedState = [| for i in 1..6 -> false |] + + let simulator = new Simulator(computers, graph, new LogZeroChance(6)) + try + simulator.Start() |> should be True + with + | Failure("Test success!") -> Assert.Pass() + | Failure("Test failure!") -> + Assert.Fail("Probabiliy == 0, but some computers were infected") + + Assert.Fail("The simulation stopped, although it shouldn't have to!") + + [] + let ``Infection should work like BFS with infection chance == 1`` () = + let computers = [| for i in 1..6 -> (new BadOS() :> IOperatingSystem) |] + let graph = + [| + [1] + [0; 2] + [1; 3] + [2; 4] + [3; 5] + [4] + |] + + let logger = new LogBFS() + let simulator = new Simulator(computers, graph, logger) + simulator.Start() |> ignore + + logger.IsBFS() |> should be True diff --git a/Semester-4/Homework-5/Network/Network.sln b/Semester-4/Homework-5/Network/Network.sln index b5704eb..121138b 100644 --- a/Semester-4/Homework-5/Network/Network.sln +++ b/Semester-4/Homework-5/Network/Network.sln @@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29613.14 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Network", "Network.fsproj", "{608891F1-5F7C-4773-95FF-9563686EDE0C}" +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 @@ -15,6 +17,10 @@ Global {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 diff --git a/Semester-4/Homework-5/Network/Program.fs b/Semester-4/Homework-5/Network/Program.fs index 99ef6ce..88b74b2 100644 --- a/Semester-4/Homework-5/Network/Program.fs +++ b/Semester-4/Homework-5/Network/Program.fs @@ -8,11 +8,11 @@ module Main = let graph = [| [1] - [0] - [3] - [2; 4; 5] + [0; 2] + [1; 3] + [2; 4] [3; 5] - [3; 4] + [4] |] let logger = new ConsoleLog() From f322603fd149e24f2b38c833582f2507f1d539b2 Mon Sep 17 00:00:00 2001 From: Timur Zinnatulin Date: Fri, 5 Jun 2020 12:12:12 +0300 Subject: [PATCH 4/5] Updated appveyor.yml --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index b5d11d6..a9f66a7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,7 @@ environment: - solution_name: Semester-4/Homework-2/TreeCalculate/TreeCalculate/TreeCalculate.sln - solution_name: Semester-4/Homework-2/PrimeSequence/PrimeSequence/PrimeSequence.sln - solution_name: Semester-4/Homework-3/LambdaInterpreter/LambdaInterpreter.sln + - solution_name: Semester-4/Homework-5/Network/Network.sln before_build: - dotnet restore %solution_name% From 3ef2abab77c0231c22bec34dcd491aca542fc1f1 Mon Sep 17 00:00:00 2001 From: Timur Zinnatulin Date: Fri, 5 Jun 2020 22:45:21 +0300 Subject: [PATCH 5/5] Now it works like BFS. --- Semester-4/Homework-5/Network.Tests/BadOS.fs | 6 --- Semester-4/Homework-5/Network.Tests/GoodOS.fs | 6 --- Semester-4/Homework-5/Network.Tests/LogBFS.fs | 21 ++------ .../Homework-5/Network.Tests/LogZeroChance.fs | 13 ++--- .../Network.Tests/Network.Tests.fsproj | 2 - .../Homework-5/Network.Tests/UnitTests.fs | 43 ++++++++-------- .../Homework-5/Network/Log/ConsoleLog.fs | 15 ++---- Semester-4/Homework-5/Network/Network.fsproj | 4 +- .../IOperatingSystem.fs | 2 +- .../Network/OperationSystem/Linux.fs | 7 --- .../Network/OperationSystem/Windows.fs | 7 --- Semester-4/Homework-5/Network/Program.fs | 9 ++-- Semester-4/Homework-5/Network/Simulation.fs | 50 +++++++++---------- 13 files changed, 63 insertions(+), 122 deletions(-) delete mode 100644 Semester-4/Homework-5/Network.Tests/BadOS.fs delete mode 100644 Semester-4/Homework-5/Network.Tests/GoodOS.fs rename Semester-4/Homework-5/Network/{OperationSystem => OperatingSystem}/IOperatingSystem.fs (73%) delete mode 100644 Semester-4/Homework-5/Network/OperationSystem/Linux.fs delete mode 100644 Semester-4/Homework-5/Network/OperationSystem/Windows.fs diff --git a/Semester-4/Homework-5/Network.Tests/BadOS.fs b/Semester-4/Homework-5/Network.Tests/BadOS.fs deleted file mode 100644 index c614d8d..0000000 --- a/Semester-4/Homework-5/Network.Tests/BadOS.fs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Network - -type BadOS () = - interface IOperatingSystem with - member this.Name = "Bad" - member this.InfectionChance = 1.0 \ No newline at end of file diff --git a/Semester-4/Homework-5/Network.Tests/GoodOS.fs b/Semester-4/Homework-5/Network.Tests/GoodOS.fs deleted file mode 100644 index c21430b..0000000 --- a/Semester-4/Homework-5/Network.Tests/GoodOS.fs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Network - -type GoodOS () = - interface IOperatingSystem with - member this.Name = "Good" - member this.InfectionChance = 0.0 \ No newline at end of file diff --git a/Semester-4/Homework-5/Network.Tests/LogBFS.fs b/Semester-4/Homework-5/Network.Tests/LogBFS.fs index b0e564c..c702ff7 100644 --- a/Semester-4/Homework-5/Network.Tests/LogBFS.fs +++ b/Semester-4/Homework-5/Network.Tests/LogBFS.fs @@ -1,29 +1,18 @@ 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 + member this.IsSomeoneHealthy = isSomeoneHealthy + member this.IsBFS = isBFS interface ILog with member this.LogState state = - let rec printList number list = - match list with - | [] -> printf "\n" - | head :: tail -> - match head with - | true -> printfn "Computer #%d: Infected" number - | false -> printfn "Computer #%d: Healthy" number - - printList (number + 1) tail - - printfn "Step %d: " stepNumber - printList 1 (state |> List.ofArray) - - if (state.[stepNumber] = false) then + + if (state.[2 - stepNumber] = false || state.[2 + stepNumber] = false) then isBFS <- false if stepNumber >= 500 then diff --git a/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs b/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs index 41c6d34..7b3d3f0 100644 --- a/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs +++ b/Semester-4/Homework-5/Network.Tests/LogZeroChance.fs @@ -1,18 +1,11 @@ namespace Network -type LogZeroChance(compNumber) = +/// Logger for network of uninfectable computers +type LogZeroChance() = let mutable stepNumber = 0 interface ILog with member this.LogState state = - if stepNumber >= 500 then - let expectedState = [| for i in 1..compNumber -> false |] - - if state = expectedState then - failwith "Test success!" - else - failwith "Test failure!" - else - stepNumber <- stepNumber + 1 + 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 index 055e071..6e4a2bc 100644 --- a/Semester-4/Homework-5/Network.Tests/Network.Tests.fsproj +++ b/Semester-4/Homework-5/Network.Tests/Network.Tests.fsproj @@ -17,8 +17,6 @@ - - diff --git a/Semester-4/Homework-5/Network.Tests/UnitTests.fs b/Semester-4/Homework-5/Network.Tests/UnitTests.fs index 65e2c01..59b3217 100644 --- a/Semester-4/Homework-5/Network.Tests/UnitTests.fs +++ b/Semester-4/Homework-5/Network.Tests/UnitTests.fs @@ -6,12 +6,13 @@ module Tests = [] let ``Simulator should work correctly with overall chance = 1`` () = - let computers = [| for i in 1..6 -> (new BadOS() :> IOperatingSystem) |] + let computers = [| for i in 1..6 -> ({new IOperatingSystem with + member this.InfectionChance = 1.0}) |] let graph = [| [1] - [0] - [3] + [0; 2] + [3; 1] [2; 4; 5] [3; 5] [3; 4] @@ -19,49 +20,45 @@ module Tests = let logger = new LogBFS() let simulator = new Simulator(computers, graph, logger) - simulator.Start() |> ignore + simulator.Start [|false; false; true; false; false; false|] |> ignore - logger.IsSomeoneHealthy() |> should be False + logger.IsSomeoneHealthy |> should be False [] let ``Simulator should work correctly with overall chance = 0`` () = - let computers = [| for i in 1..6 -> (new GoodOS() :> IOperatingSystem) |] + let computers = [| for i in 1..6 -> ({new IOperatingSystem with + member this.InfectionChance = 0.0}) |] let graph = [| [1] - [0] - [3] + [0; 2] + [1; 3] [2; 4; 5] [3; 5] [3; 4] |] - let expectedState = [| for i in 1..6 -> false |] + let expectedState = Array.concat[ [|true|]; [| for i in 1..5 -> false |] ] + let log = new LogZeroChance() - let simulator = new Simulator(computers, graph, new LogZeroChance(6)) - try - simulator.Start() |> should be True - with - | Failure("Test success!") -> Assert.Pass() - | Failure("Test failure!") -> - Assert.Fail("Probabiliy == 0, but some computers were infected") - - Assert.Fail("The simulation stopped, although it shouldn't have to!") + 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 BadOS() :> IOperatingSystem) |] + 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; 5] - [4] + [3] |] let logger = new LogBFS() let simulator = new Simulator(computers, graph, logger) - simulator.Start() |> ignore + simulator.Start [|false; false; true; false; false|] |> ignore - logger.IsBFS() |> should be True + 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 index a9dac01..6485f5b 100644 --- a/Semester-4/Homework-5/Network/Log/ConsoleLog.fs +++ b/Semester-4/Homework-5/Network/Log/ConsoleLog.fs @@ -7,18 +7,11 @@ type ConsoleLog() = interface ILog with /// Prints current network state member this.LogState state = - let rec printList number list = - match list with - | [] -> printf "\n" - | head :: tail -> - match head with - | true -> printfn "Computer №%d: Infected" number - | false -> printfn "Computer №%d: Healthy" number - - printList (number + 1) tail - printfn "Step №%d. " step - printList 1 (state |> List.ofArray) + 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/Network.fsproj b/Semester-4/Homework-5/Network/Network.fsproj index 3ed6223..075f49f 100644 --- a/Semester-4/Homework-5/Network/Network.fsproj +++ b/Semester-4/Homework-5/Network/Network.fsproj @@ -8,9 +8,7 @@ - - - + diff --git a/Semester-4/Homework-5/Network/OperationSystem/IOperatingSystem.fs b/Semester-4/Homework-5/Network/OperatingSystem/IOperatingSystem.fs similarity index 73% rename from Semester-4/Homework-5/Network/OperationSystem/IOperatingSystem.fs rename to Semester-4/Homework-5/Network/OperatingSystem/IOperatingSystem.fs index a771934..79f2b2b 100644 --- a/Semester-4/Homework-5/Network/OperationSystem/IOperatingSystem.fs +++ b/Semester-4/Homework-5/Network/OperatingSystem/IOperatingSystem.fs @@ -2,5 +2,5 @@ /// Describes the operating system interface type IOperatingSystem = - abstract member Name : string + /// Chance of the computer getting infected abstract member InfectionChance : float \ No newline at end of file diff --git a/Semester-4/Homework-5/Network/OperationSystem/Linux.fs b/Semester-4/Homework-5/Network/OperationSystem/Linux.fs deleted file mode 100644 index 392a5a5..0000000 --- a/Semester-4/Homework-5/Network/OperationSystem/Linux.fs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Network - -/// Linux OS -type Linux() = - interface IOperatingSystem with - member this.Name = "Linux" - member this.InfectionChance = 0.3 \ No newline at end of file diff --git a/Semester-4/Homework-5/Network/OperationSystem/Windows.fs b/Semester-4/Homework-5/Network/OperationSystem/Windows.fs deleted file mode 100644 index ef80307..0000000 --- a/Semester-4/Homework-5/Network/OperationSystem/Windows.fs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Network - -/// Windows OS -type Windows() = - interface IOperatingSystem with - member this.Name = "Windows" - member this.InfectionChance = 0.8 \ No newline at end of file diff --git a/Semester-4/Homework-5/Network/Program.fs b/Semester-4/Homework-5/Network/Program.fs index 88b74b2..eb69c0d 100644 --- a/Semester-4/Homework-5/Network/Program.fs +++ b/Semester-4/Homework-5/Network/Program.fs @@ -3,19 +3,18 @@ module Main = open System - let computers = Array.concat [ [| for i in 1..3 -> (new Windows() :> IOperatingSystem) |] - ; [| for i in 1..3 -> (new Linux() :> IOperatingSystem) |] ] + 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; 5] - [4] + [3] |] let logger = new ConsoleLog() let simulator = new Simulator(computers, graph, logger) - simulator.Start () |> ignore \ No newline at end of file + 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 index 6ecebdf..9f47831 100644 --- a/Semester-4/Homework-5/Network/Simulation.fs +++ b/Semester-4/Homework-5/Network/Simulation.fs @@ -8,11 +8,12 @@ type Simulator( let random = System.Random() + /// Starts the simulation - member this.Start () = + member this.Start (startState : bool array) = /// Carries out the simulation steps - let rec nextStep (handlingQueue : int list) (used : bool array) = + let rec nextStep (handlingQueue : int list) (used : bool array) (newQueue : int list) = match handlingQueue with /// Computer gets infected @@ -20,37 +21,36 @@ type Simulator( not used.[head] && (random.NextDouble() < computers.[head].InfectionChance) -> used.[head] <- true - used |> log.LogState |> ignore - - nextStep (handlingQueue @ graph.[head]) used + nextStep tail used (newQueue @ graph.[head]) /// Computer does not get infected /// Keeps trying to infect it | head :: tail when not used.[head] -> - used |> log.LogState |> ignore - nextStep (handlingQueue @ [head]) used + + /// 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 + nextStep tail used newQueue /// Empty queue - | [] -> used + | [] -> + (newQueue, used) /// Launches the virus into the network - let rec virusJump i (state : bool array) = - - /// All the computers are infected - if (i = computers.Length) then - true - else - match state.[i] with - | true -> virusJump (i + 1) state - | false -> - /// Tries to infect i-th computer - let newState = nextStep [i] state - virusJump (i + 1) newState - - let startingState = [| for i in 1 .. computers.Length -> false|] - - virusJump 0 startingState \ No newline at end of file + 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