-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Local network graph is ready #8
base: master
Are you sure you want to change the base?
Changes from 12 commits
2bfa5a7
54681b3
41aa2f4
947398e
9856884
ef51c1e
c60c94b
34c11ba
5589efc
de03a6e
8c863e9
00e08ef
560cf37
554d53d
4244717
41a73e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
| ||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.30114.105 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "LocalNetworkGraph", "LocalNetworkGraph\LocalNetworkGraph.fsproj", "{3DD18E22-393F-4B15-ACD5-AF3DA21A5CC2}" | ||
EndProject | ||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LocalNetworkGraphTests", "LocalNetworkGraphTests\LocalNetworkGraphTests.fsproj", "{61D8FBF7-9B8A-461B-A27F-0416A7085DB3}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{3DD18E22-393F-4B15-ACD5-AF3DA21A5CC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{3DD18E22-393F-4B15-ACD5-AF3DA21A5CC2}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{3DD18E22-393F-4B15-ACD5-AF3DA21A5CC2}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{3DD18E22-393F-4B15-ACD5-AF3DA21A5CC2}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{61D8FBF7-9B8A-461B-A27F-0416A7085DB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{61D8FBF7-9B8A-461B-A27F-0416A7085DB3}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{61D8FBF7-9B8A-461B-A27F-0416A7085DB3}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{61D8FBF7-9B8A-461B-A27F-0416A7085DB3}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {70F6F8E0-B63F-4D25-9686-6ACC16C8D9F5} | ||
EndGlobalSection | ||
EndGlobal |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
module LocalNetwork | ||
|
||
open System | ||
|
||
|
||
/// Local network working process model. | ||
type LocalNetwork(computersCommunication: int list list, OSOfComputers: string list, probabilityInfectionForOS: float list) = | ||
|
||
/// Infected computers. | ||
let mutable infected = [] | ||
|
||
/// Infected this step. | ||
let mutable newInfected = [] | ||
|
||
/// Number of computers in local network. | ||
let numberOfComputers () = List.length computersCommunication | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это можно было сделать полем, ведь computersCommunication немутабельный, его длину можно сосчитать один раз и она не сможет измениться |
||
|
||
/// Random number sensor for computers. On every step check if the computer is infected. | ||
let rndSensorValue = new Random() | ||
|
||
/// Returns the probability to be infected for computer with specific OS. | ||
let probabylityOfInfectionForOS operSys = probabilityInfectionForOS.[List.findIndex (fun x -> x = operSys) OSOfComputers] * 100.0 | ||
|
||
/// Finds probabylity of infection for computer. | ||
let probabilityOfInfection vertex = probabylityOfInfectionForOS <| OSOfComputers.[vertex] | ||
|
||
/// Checks if the current step infects computer. | ||
let isInfectedThisStep vertex = | ||
probabilityOfInfection vertex >= double(rndSensorValue.Next(0, 100)) | ||
|
||
/// Checks if the network can be infected. | ||
let networkCanBeInfected = List.exists (fun x -> abs(x) > 0.001) probabilityInfectionForOS | ||
|
||
/// Checks if the neighbours of the computer can be infected. | ||
let neighboursCanBeInfected vertex = | ||
List.exists (fun x -> not (List.contains x infected) && abs(probabilityOfInfection x) > 0.001) computersCommunication.[vertex] | ||
|
||
/// Tries to infect neighbours. | ||
let tryInfectNeighbours vertex = | ||
let tryInfectNeighboursRec vertex = | ||
computersCommunication.[vertex] | ||
|> List.iter (fun x -> if not (List.contains x infected) && isInfectedThisStep x then newInfected <- newInfected @ [x]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
tryInfectNeighboursRec vertex | ||
|
||
/// Infects first computer. | ||
let infectFirst () = | ||
let rec infectFirstRec acc = | ||
if isInfectedThisStep acc then acc | ||
else infectFirstRec <| (acc + 1) % numberOfComputers() | ||
infectFirstRec 0 | ||
|
||
/// Prints the information about the state of the network. | ||
let printInf () = | ||
let rec printRec currVertex = | ||
if currVertex < numberOfComputers() then | ||
if List.contains currVertex infected then printfn "%s%d" "INFECTED: " currVertex | ||
else printfn "%s%d" "Not infected: " currVertex | ||
printRec (currVertex + 1) | ||
printf "%s" "\n" | ||
printRec 0 | ||
|
||
/// Infects all the vertexes that are possible to infect. | ||
let rec infectAll = | ||
if not networkCanBeInfected then infected | ||
else | ||
let rec infectAllRec acc = | ||
if List.length infected = 0 then | ||
infected <- infected @ [infectFirst ()] | ||
printInf () | ||
infectAllRec 0 | ||
elif (List.length infected = numberOfComputers () || List.forall (fun x -> not (neighboursCanBeInfected x)) infected) then infected | ||
else | ||
List.iter(fun x -> tryInfectNeighbours x) infected | ||
infected <- infected @ newInfected | ||
printInf () | ||
infectAllRec 0 | ||
infectAllRec 0 | ||
|
||
/// Infects all the computers with virus. Returns infected computers. | ||
member public this.Infected = infectAll | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тогда оно должно называться как что-то вроде "Infect" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Compile Include="LocalNetwork.fs" /> | ||
<Compile Include="Program.fs" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Learn more about F# at http://fsharp.org | ||
|
||
open System | ||
open LocalNetwork | ||
|
||
[<EntryPoint>] | ||
let main argv = | ||
printfn "%A" <| LocalNetwork([[1; 3]; [0]; [3]; [2; 1]], ["Windows"; "Linux"; "Linux"; "Mac OS"], | ||
[0.7; 0.1; 0.1; 0.9]).Infected | ||
|
||
0 // return an integer exit code |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
|
||
<IsPackable>false</IsPackable> | ||
<GenerateProgramFile>true</GenerateProgramFile> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="FsUnit" Version="3.8.1" /> | ||
<PackageReference Include="nunit" Version="3.12.0" /> | ||
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Compile Include="LocalNetworkTests.fs" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\LocalNetworkGraph\LocalNetworkGraph.fsproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Update="FSharp.Core" Version="4.7.2" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
module LocalNetworkGraphTests | ||
|
||
open NUnit.Framework | ||
open LocalNetwork | ||
open FsUnit | ||
|
||
let testCases1 = | ||
[ | ||
[[1]; [0]], ["Linux"; "Windows"], [0.3; 0.7], [0; 1] | ||
[[1]; [0]], ["Linux"; "Windows"], [1.0; 1.0], [0; 1] | ||
[[1]; [0]], ["Mac OS"; "Linux"], [0.7; 0.0], [0] | ||
[[1; 3]; [0]; [3]; [2; 1]], ["Windows"; "Linux"; "Linux"; "Mac OS"], [0.7; 0.1; 0.1; 0.9], [0; 1; 2; 3] | ||
[[1; 2; 3; 4]; [0; 2; 3; 4]; [0; 1; 3; 4]; [0; 1; 2; 3]; [0; 1; 2; 3; 4]], | ||
["WIndows"; "Windows"; "Linux"; "Linux"; "Mac OS"], [0.5; 0.5; 0.2; 0.2; 1.0], [0; 1; 2; 3; 4] | ||
] |> List.map (fun (communicationComputers, operSys, probabOfInf, infected) -> | ||
TestCaseData(communicationComputers, operSys, probabOfInf, infected)) | ||
|
||
let testCases2 = | ||
[ | ||
[[1]; [0]], ["Linux"; "Windows"], [0.0; 0.0] | ||
[[1; 2; 3; 4]; [0; 2; 3; 4]; [0; 1; 3; 4]; [0; 1; 2; 3]; [0; 1; 2; 3; 4]], | ||
["WIndows"; "Windows"; "Linux"; "Linux"; "Mac OS"], [0.0; 0.0; 0.0; 0.0; 0.0] | ||
] |> List.map (fun (communicationComputers, operSys, probabOfInf) -> | ||
TestCaseData(communicationComputers, operSys, probabOfInf)) | ||
|
||
[<Test>] | ||
[<TestCaseSource("testCases1")>] | ||
let ``Checks if contains vertexes that should be infected`` communication operSys probabOfInf infected = | ||
LocalNetwork(communication, operSys, probabOfInf).Infected.TrueForAll(fun x -> List.contains x infected) |> should equal true | ||
|
||
[<Test>] | ||
[<TestCaseSource("testCases1")>] | ||
let ``Checks if vertexes that should be infected are contained in result`` communication operSys probabOfInf infected = | ||
List.forall(fun x -> LocalNetwork(communication, operSys, probabOfInf).Infected.Contains(x)) infected |> should equal true | ||
|
||
[<Test>] | ||
[<TestCaseSource("testCases2")>] | ||
let ``Checks if the algorithm works correctly when probabylity of infection is 0 for all computers`` communication operSys probabOfInf = | ||
LocalNetwork(communication, operSys, probabOfInf).Infected.Count = 0 |> should equal true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Так нет, функциональный стиль --- это не когда у нас поле немутабельного типа, котрое по сути представляет собой глобальную переменную, его кто-то где-то внутри меняет, потом его надо не забыть сбросить в пустой список и т.д., функциональный стиль --- это когда у нас практически нет состояния и мы всё, что надо, просто возвращаем из функций или передаём как параметр, так что поток данных в программе в точности соответствует потоку исполнения. Тут можно было сделать так, чтобы tryInfectNeighbours выдавал список заражённых, а вместо
List.iter(fun x -> tryInfectNeighbours x) infected
(что само по себе не очень, правильно List.iter tryInfectNeighbours infected) сделать List.map и List.concatThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
И мне кажется, как раз забыли сбросить newInfected :)