using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace consoleKNIR
{
class TaskManagement
{
int tasksLeft = 0;
int numberOfTasks;
int workUnitNumber;
double time = 0;
int numberOfUsers;
int numberOfChecks;
// массив заданий, инициализируется нулями в конструкторе, по мере выполнения заданий заполняется единицами
public int[][] tasks;
// массив, в котором хранится время выполнения каждого задания
public double[] tasksTime;
// массив, в котором хранится выполнение каждой итерации(успешное или нет)
//первоначально забит нулями
public int[] successCheck;
int failure;
double workUnitTime;
// конструктор принимает число заданий, число work-unit'ов на которые делятся задания, количество пользователей
// которым выдается задания и шанс на отказ в процентах
public TaskManagement(int numberOfTasks, int workUnitNumber, int numberOfUsers, int numberOfChecks, int failure, double EV, double sigma)
{
this.numberOfTasks = numberOfTasks;
this.workUnitNumber = workUnitNumber;
this.numberOfChecks = numberOfChecks;
this.numberOfUsers = numberOfUsers;
this.tasks = new int[numberOfTasks][];
this.tasksTime = new double[numberOfTasks];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = new int[workUnitNumber];
for (int j = 0; j < tasks[i].Length; j++)
{
tasks[i][j] = numberOfChecks+1;
}
tasksTime[i] = 0;
}
this.failure = failure;
this.workUnitTime = this.NormalDistribution(EV, sigma);
this.successCheck = new int[numberOfTasks];
for (int i = 0; i < successCheck.Length; i++)
{
successCheck[i] = 0;
}
}
// Проверяем успешность подсчета work-unit'a
public bool CheckFailure()
{
Random random = new Random();
int check = random.Next(1, 101);
if (check > failure)
return true;
else
return false;
}
// Вычисляем время вычисления с помощью нормального распределения(ЦПТ)
// параметрами является математичесок ожидание и отклонение
public double NormalDistribution(double mo, double sigma)
{
double Sum = 0;
double ndValue = 0;
Random rand = new Random();
for (int i = 0; i <= 12; i++)
{
double R = rand.NextDouble();
Sum = Sum + R;
}
ndValue = Math.Round((mo + sigma * (Sum - 6)), 3);
return ndValue;
}
//функция генерирует одну итерацию (раздачу пользователям заданий)
public int[] GenerateIteration()
{
Random rand = new Random();
int[] users = new int[numberOfUsers];
for (int i = 0; i < users.Length; i++)
{
users[i] = -1;
}
for (int i = 0; i < users.Length; i++)
{
int randomtask = rand.Next(0, numberOfTasks);
// если задание выполнено не полностью (у последнего work-unit'а задания индекс не равен 1)
if (tasks[randomtask][workUnitNumber - 1] != 1)
{
while (users.Contains(randomtask) || tasks[randomtask][workUnitNumber - 1] == 1)
{
randomtask = rand.Next(0, numberOfTasks);
}
users[i] = randomtask;
}
else
{
while ((users.Contains(randomtask)) || (tasks[randomtask][workUnitNumber - 1] == 1))
{
randomtask = rand.Next(0, numberOfTasks);
//rand.Next(
}
users[i] = randomtask;
}
}
return users;
}
//функция проверяет выполнены ли все задания
bool CompletionCheck()
{
int counter = 0;
for (int i = 0; i < numberOfTasks; i++)
{
if (tasks[i][workUnitNumber - 1] == 1)
counter++;
}
if (counter == numberOfTasks)
return true;
else
{
tasksLeft = numberOfTasks - counter;
if (tasksLeft < numberOfUsers)
numberOfUsers = tasksLeft;
return false;
}
}
//функция считает время которое необходимо на просчет всех заданий
//а также вносит в массив в какой момент времени каждое задание было завершено
public double CalcTime()
{
while (!this.CompletionCheck())
{
int[] iteration = this.GenerateIteration();
Array.Sort(iteration);
for (int i = 0; i < iteration.Length; i++)
{
if (this.CheckFailure()) //&& iteration[i] != -1)
{
int progress = 0;
for (int j = 0; j < workUnitNumber; j++)
{
if (tasks[iteration[i]][j] == 1)
progress++;
}
if (progress != workUnitNumber)
{
tasks[iteration[i]][progress] = tasks[iteration[i]][progress] - 1;
if (progress == workUnitNumber-1)
{
tasksTime[iteration[i]] = time + workUnitTime;
}
}
}
}
time = time + workUnitTime;
}
return time;
}
}
class Program
{
static void Main(string[] args)
{
//количество заданий, количество work-unit'ов, количество участников, количество проверок, процент отказа, мат ожидание, отклонение
TaskManagement a = new TaskManagement(100, 1, 10, 3, -1, 4, 0);
double time = a.CalcTime();
double[] taskTime = a.tasksTime;
Console.WriteLine("{0:f3}", time);
Console.ReadLine();
}
}
}