diff --git a/ComputerNet/ComputerNet.Tests/ComputerNet.Tests.fsproj b/ComputerNet/ComputerNet.Tests/ComputerNet.Tests.fsproj new file mode 100644 index 0000000..8a67a79 --- /dev/null +++ b/ComputerNet/ComputerNet.Tests/ComputerNet.Tests.fsproj @@ -0,0 +1,37 @@ + + + + net7.0 + + false + false + true + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive +all + + runtime; build; native; contentfiles; analyzers; buildtransitive +all + + + + + + + + + + + + + diff --git a/ComputerNet/ComputerNet.Tests/Program.fs b/ComputerNet/ComputerNet.Tests/Program.fs new file mode 100644 index 0000000..5da7e48 --- /dev/null +++ b/ComputerNet/ComputerNet.Tests/Program.fs @@ -0,0 +1,5 @@ +module Program = + + [] + let main _ = 0 + diff --git a/ComputerNet/ComputerNet.Tests/UnitTest.fs b/ComputerNet/ComputerNet.Tests/UnitTest.fs new file mode 100644 index 0000000..c915061 --- /dev/null +++ b/ComputerNet/ComputerNet.Tests/UnitTest.fs @@ -0,0 +1,68 @@ +module ComputerNet.Tests + +open NUnit.Framework +open FsUnit +open ComputerNet.Computer +open ComputerNet.Net + +let ``adjacency matrix`` = + seq { + TestCaseData([| + [| 0; 0; 0; 1; 1 |] + [| 1; 0; 0; 0; 0|] + [| 1; 0; 0; 0; 0|] + [| 0; 0; 1; 0; 0|] + [| 0; 1; 0; 0; 0|] + |] + ) + } + +let ``adjacency matrix detached case`` = + seq { + TestCaseData([| + [| 0; 0; 0; 1; 0 |] + [| 0; 0; 0; 0; 0|] + [| 1; 0; 0; 0; 0|] + [| 0; 0; 1; 0; 0|] + [| 0; 1; 0; 0; 0|] + |] + ) + } +let ``check mac adresses`` correct result = List.map (fun (c : Computer) -> c.macAdress) result |> should equal correct + +[] +let ``detached computers should't be infected`` (matrix : array>) = + let computers = [ Computer(1, "Linux", 1.0, true); + Computer(2, "Linux", 1.0, false); + Computer(3, "Windows", 1.0, false); + Computer(4, "Linux", 1.0, false); + Computer(5, "macOS", 1.0, false)] + let net = Net(computers, matrix) + net.SpreadVirus() |> ignore + net.SpreadVirus() |> ignore + computers |> List.filter (fun (c : Computer) -> not c.isDeseased) |> + ``check mac adresses`` [ 2; 5; ] + +[] +let ``all net with probability 1 should spread virus in bfs way`` (matrix : array>) = + let computers = [ Computer(1, "Linux", 1.0, true); + Computer(2, "Linux", 1.0, false); + Computer(3, "Windows", 1.0, false); + Computer(4, "Linux", 1.0, false); + Computer(5, "macOS", 1.0, false)] + let net = Net(computers, matrix) + let infectedComputer = net.GetDeseasedComputers().[0] + infectedComputer.SpreadVirus() + net.GetDeseasedComputers() |> ``check mac adresses`` [ 1; 4; 5;] + net.SpreadVirus() |> should equal true + +[] +let ``net with probabilities only 0 shouldn't have any deseased computers``(matrix : array>) = + let computers = [ Computer(1, "Linux", 0.0, true); + Computer(2, "Linux", 0.0, false); + Computer(3, "Windows", 0.0, false); + Computer(4, "Linux", 0.0, false); + Computer(5, "macOS", 0.0, false)] + let net = Net(computers, matrix) + net.SpreadVirus() |> should equal true + net.GetDeseasedComputers() |> ``check mac adresses`` [ 1; ] \ No newline at end of file diff --git a/ComputerNet/ComputerNet.sln b/ComputerNet/ComputerNet.sln new file mode 100644 index 0000000..57ccfb9 --- /dev/null +++ b/ComputerNet/ComputerNet.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 25.0.1706.10 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ComputerNet", "ComputerNet\ComputerNet.fsproj", "{C81B6B32-DFBF-4F73-8457-2247AB4081EC}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ComputerNet.Tests", "ComputerNet.Tests\ComputerNet.Tests.fsproj", "{C4BE4761-4777-496C-8440-29E18A942A22}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C81B6B32-DFBF-4F73-8457-2247AB4081EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C81B6B32-DFBF-4F73-8457-2247AB4081EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C81B6B32-DFBF-4F73-8457-2247AB4081EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C81B6B32-DFBF-4F73-8457-2247AB4081EC}.Release|Any CPU.Build.0 = Release|Any CPU + {C4BE4761-4777-496C-8440-29E18A942A22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4BE4761-4777-496C-8440-29E18A942A22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4BE4761-4777-496C-8440-29E18A942A22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4BE4761-4777-496C-8440-29E18A942A22}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B87D30DF-6E22-48A9-B465-1D46905AFF02} + EndGlobalSection +EndGlobal diff --git a/ComputerNet/ComputerNet/Computer.fs b/ComputerNet/ComputerNet/Computer.fs new file mode 100644 index 0000000..e5a4f70 --- /dev/null +++ b/ComputerNet/ComputerNet/Computer.fs @@ -0,0 +1,40 @@ +namespace ComputerNet + +open System + +module Computer = + + type Computer (macAdress : int, OS : string, + infectionProbability : float, isDeseasedArg : bool) = + + let mutable neighbours : Computer list = [] + + member val macAdress = macAdress with get + + member val OS = OS with get + + member val infectionProbability = infectionProbability with get + + member val isDeseased = isDeseasedArg with get, set + + static member random = new System.Random() + + member computer.addNeighbour (neighbour : Computer) = + neighbours <- neighbour :: neighbours + + member computer.getDeseased () = + + let number = Computer.random.Next(0, 100) + + let isDeseased = infectionProbability |> (*) 100.0 |> int |> (-) number |> (>) 0 + + computer.isDeseased <- isDeseased + + member computer.SpreadVirus () = + + List.iter (fun (neighbour : Computer) -> (neighbour.getDeseased())) neighbours + + member computer.checkIfAllNeighboursAreDeseased () = + + List.forall (fun (neigbour : Computer) -> + (neigbour.isDeseased || neigbour.infectionProbability = 0.0)) neighbours \ No newline at end of file diff --git a/ComputerNet/ComputerNet/ComputerNet.fsproj b/ComputerNet/ComputerNet/ComputerNet.fsproj new file mode 100644 index 0000000..dc974a3 --- /dev/null +++ b/ComputerNet/ComputerNet/ComputerNet.fsproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + + + + + + + + + diff --git a/ComputerNet/ComputerNet/Net.fs b/ComputerNet/ComputerNet/Net.fs new file mode 100644 index 0000000..44e9da9 --- /dev/null +++ b/ComputerNet/ComputerNet/Net.fs @@ -0,0 +1,36 @@ +namespace ComputerNet + +open System +open ComputerNet.Computer + +module Net = + type Net (computers : Computer list, adjacencyMatrix : int[][]) = + + let computers = computers + + let adjacencyMatrix = adjacencyMatrix + + do + for i = 0 to computers.Length - 1 do + for j = 0 to computers.Length - 1 do + if adjacencyMatrix.[i].[j] = 1 then + computers.[i].addNeighbour(computers.[j]) |> ignore + + + member val IsAllComputersDeseased = false + + member this.GetDeseasedComputers () = + + List.filter (fun (computer : Computer) -> computer.isDeseased) computers + + member this.SpreadVirus () = + + if this.IsAllComputersDeseased then true + else + if (List.length (this.GetDeseasedComputers()) = List.length computers) then + true + else + let isAllNeigboursDeseased = true + let deseased = this.GetDeseasedComputers() + List.iter (fun (computer : Computer) -> computer.SpreadVirus()) deseased + List.forall (fun (computer : Computer) -> computer.checkIfAllNeighboursAreDeseased()) deseased \ No newline at end of file diff --git a/ComputerNet/ComputerNet/Program.fs b/ComputerNet/ComputerNet/Program.fs new file mode 100644 index 0000000..31f8f03 --- /dev/null +++ b/ComputerNet/ComputerNet/Program.fs @@ -0,0 +1 @@ +namespace ComputerNet