#region License Information
/* HeuristicLab
* Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using HeuristicLab.Clients.Hive.WebJobManager.Services;
using HeuristicLab.Optimization;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Linq;
using System.Reflection;
using HeuristicLab.Core;
namespace HeuristicLab.Clients.Hive.WebJobManager
{
///
/// SignalR Hub for displaying the progress when uploading a Job.
/// Also used to change child distribution and priority for inner tasks.
///
public class ProgressHub : Hub
{
private WebLoginService weblog;
private Guid userId;
private FileOpeningService fileopener;
private void loader()
{
weblog = WebLoginService.Instance;
string uid = Context.QueryString["userid"];
if (uid == null || uid == "" || Guid.Parse(uid) == Guid.Empty)
{
userId = Guid.Empty;
}
else
{
userId = Guid.Parse(uid);
fileopener = weblog.getFileOpener(userId);
}
}
///
/// First message from client
///
/// Client message
public void HandleMessage(string receivedString)
{
loader();
Clients.Caller.processMessage("Connection Established");
fileopener.Job.Progress.StatusChanged += runHub;
}
///
/// Changes name for the current job to be created
///
/// Job name
public void ChangeNameResource(string name, string resource)
{
loader();
if (name != null)
fileopener.Job.Job.Name = name;
if (resource != null && resource != "")
{
fileopener.Job.Job.ResourceNames += "/" + resource;
}
}
///
/// Toggles distribute child task for a current task
///
/// 2-dimensional int array.
/// First dimension is depth (arr.length == 4 means the item is 4 nodes deep)
/// Second contains expirement info or batch info. (arr[][0] contains index to select the right experiment sub task,
/// arr[][1] contains index to select right batch run subtask)
public void ToggleChild(int[][] arr)
{
loader();
bool change = false;
string name = "";
HiveTask current = fileopener.Job.HiveTasks.ToList()[0];
if (arr.Length == 0)
{//check if upper job
current.ItemTask.ComputeInParallel = !current.ItemTask.ComputeInParallel;
change = current.ItemTask.ComputeInParallel;
name = current.ItemTask.Name;
}
else
{
for (var i = 0; i < arr.Length; i++)
{
//loop for depth
if (i == arr.Length - 1)//end of depth loop, right current is selected
{
if (current.ItemTask.Item is BatchRun)
{
current.ChildHiveTasks[arr[i][1]].ItemTask.ComputeInParallel = !current.ChildHiveTasks[arr[i][1]].ItemTask.ComputeInParallel;
change = current.ChildHiveTasks[arr[i][1]].ItemTask.ComputeInParallel;
name = current.ChildHiveTasks[arr[i][1]].ItemTask.Name;
}
else if (current.ItemTask.Item is Experiment)
{
current.ChildHiveTasks[arr[i][0]].ItemTask.ComputeInParallel = !current.ChildHiveTasks[arr[i][0]].ItemTask.ComputeInParallel;
change = current.ChildHiveTasks[arr[i][0]].ItemTask.ComputeInParallel;
name = current.ChildHiveTasks[arr[i][0]].ItemTask.Name;
}
}
else
{//not deep enough, select right path
if (current.ItemTask.Item is BatchRun)
current = current.ChildHiveTasks[arr[i][1]]; // select right batch
else if (current.ItemTask.Item is Experiment)
current = current.ChildHiveTasks[arr[i][0]]; // select right sub task from experiment
}
}
}
if (change)
Clients.Caller.saveComplete("Child distribution activated for " + name);
else
Clients.Caller.saveComplete("Child distribution deactivated for " + name);
}
public void changeName(int[][] arr, string name, int idname)
{
if (name != "" && name != null)
{
loader();
string old = "";
HiveTask current = fileopener.Job.HiveTasks.ToList()[0];
if (arr.Length == 0)
{//check if upper job
old = current.ItemTask.Name;
current.ItemTask.Name = name;
}
else
{
for (var i = 0; i < arr.Length; i++)
{//loop for depth
if (i == arr.Length - 1)
{//Right depth reached, change name for current
if (current.ItemTask.Item is BatchRun)
{
old = current.ChildHiveTasks[arr[i][1]].ItemTask.Name;
current.ChildHiveTasks[arr[i][1]].ItemTask.Name = name;
}
else if (current.ItemTask.Item is Experiment)
{
old = current.ChildHiveTasks[arr[i][0]].ItemTask.Name;
current.ChildHiveTasks[arr[i][0]].ItemTask.Name = name;
}
}
else
{//not deep enough, choose right path
if (current.ItemTask.Item is BatchRun)
current = current.ChildHiveTasks[arr[i][1]]; // select right batch
else if (current.ItemTask.Item is Experiment)
current = current.ChildHiveTasks[arr[i][0]]; // select right sub task from experiment
}
}
}
Clients.Caller.processName(name, idname);
Clients.Caller.saveComplete( old + " renamed to " + name);
}
}
public void changeRepit(int[][] arr, int repit)
{
loader();
HiveTask current = fileopener.Job.HiveTasks.ToList()[0];
string Name = "failed";
if (arr.Length == 0)
{//check if upper job
if (current.ItemTask.Item is BatchRun)
{
var b = (BatchRun)current.ItemTask.Item;
b.Repetitions = repit;
Name = current.ItemTask.Name;
}
}
else
{
for (var i = 0; i < arr.Length; i++)
{//loop for depth
if (i == arr.Length - 1)
{//Right depth reached, change name for current
if (current.ChildHiveTasks[arr[i][0]].ItemTask.Item is BatchRun)
{
var b = (BatchRun)current.ChildHiveTasks[arr[i][0]].ItemTask.Item;
b.Repetitions = repit;
Name = current.ChildHiveTasks[arr[i][0]].ItemTask.Name;
}
}
else
{//not deep enough, choose right path
if (current.ItemTask.Item is BatchRun)
current = current.ChildHiveTasks[arr[i][1]]; // select right batch
else if (current.ItemTask.Item is Experiment)
current = current.ChildHiveTasks[arr[i][0]]; // select right sub task from experiment
}
}
}
if (Name == "failed")
Clients.Caller.createAlert("Something went wrong while changing the repititions, please try again", "danger");
else
Clients.Caller.saveComplete("Repititions changed to "+repit+ " for " + Name);
}
///
/// Change priority for a node
///
/// 2-dimensional int array.
/// First dimension is depth (arr.length == 4 means the item is 4 nodes deep)
/// Second contains expirement info or batch info. (arr[][0] contains index to select the right experiment sub task,
/// arr[][1] contains index to select right batch run subtask)
/// Selected priority
public void ChangePriority(int[][] arr, int prior)
{
string name = "";
loader();
HiveTask current = fileopener.Job.HiveTasks.ToList()[0];
if (arr.Length == 0)
{//check if upper job
current.Task.Priority = prior;
name = current.ItemTask.Name;
}
else
{
for (var i = 0; i < arr.Length; i++)
{//loop for depth
if (i == arr.Length - 1)
{//Right depth reached, change priority for current
if (current.ItemTask.Item is BatchRun)
{
current.ChildHiveTasks[arr[i][1]].Task.Priority = prior;
name = current.ChildHiveTasks[arr[i][0]].ItemTask.Name;
}
else if (current.ItemTask.Item is Experiment)
{
current.ChildHiveTasks[arr[i][0]].Task.Priority = prior;
name = current.ChildHiveTasks[arr[i][0]].ItemTask.Name;
}
}
else
{//not deep enough, choose right path
if (current.ItemTask.Item is BatchRun)
current = current.ChildHiveTasks[arr[i][1]]; // select right batch
else if (current.ItemTask.Item is Experiment)
current = current.ChildHiveTasks[arr[i][0]]; // select right sub task from experiment
}
}
}
Clients.Caller.saveComplete("Priority changed for " + name);
}
///
/// Used by event 'ProgressChanged' from current uploading Job
///
///
///
public void runHub(object sender, EventArgs e)
{
loader();
int value = 0;
switch (fileopener.Job.Progress.Status)
{
case "Connecting to server...":
value = 0;
break;
case "Uploading Job...":
value = 10;
break;
case "Uploading plugins...":
value = 30;
break;
case "Uploading tasks...":
value = 50;
break;
case "Upload finished":
value = 100;
break;
default://Tasks are uploading individually
value = (int)(50 + (40 * fileopener.Job.Progress.ProgressValue));
break;
}
//send info to client
Clients.Caller.processMessage(fileopener.Job.Progress.Status, value);
}
public void paraEdit(int[][] arr, string problem, string name, string type, string value)
{
loader();
HiveTask current = fileopener.Job.HiveTasks.ToList()[0];
if (arr.Length == 0)
{//check if upper job
if (current.ItemTask.Item is Algorithm)
{
searchEditPara(current, problem, name, type, value);
}
}
else
{
for (var i = 0; i < arr.Length; i++)
{//loop for depth
if (i == arr.Length - 1)
{//Right depth reached, change priority for current
if (current.ItemTask.Item is BatchRun)
{
current = current.ChildHiveTasks[arr[i][1]];
}
else if (current.ItemTask.Item is Experiment)
{
current = current.ChildHiveTasks[arr[i][0]];
}
if (current.ItemTask.Item is Algorithm)
{
searchEditPara(current, problem, name, type, value);
}
}
else
{//not deep enough, choose right path
if (current.ItemTask.Item is BatchRun)
current = current.ChildHiveTasks[arr[i][1]]; // select right batch
else if (current.ItemTask.Item is Experiment)
current = current.ChildHiveTasks[arr[i][0]]; // select right sub task from experiment
}
}
}
}
///
/// Generic parameter setter
///
/// Current task to edit
/// Problem parameter or normal parameter
/// Property name
/// Datatype
/// New value
private void searchEditPara(HiveTask curr, string problem, string name, string type, string value)
{
var prob = problem == "True" ? true : false;
var dattype = Type.GetType(type);
if (dattype == null)
{//Use assemblies to find correct datatype
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
dattype = a.GetType(type);
if (dattype != null)
break;
}
}
//find parse method
var parse = dattype.GetMethod("Parse", new[] { typeof(string) });
if (parse != null)
{
//Parses string to correct datatype
var val = parse.Invoke(null, new object[] { value });
//BUGGERS
// if (name == "DominateOnEqualQualities" || name == "PlusSelection" || name == "ReevaluteElites")
// val = ((BoolValue)val).Value;
// if (name == "ReduceToPopulationSize")
//name += "Parameter";
if (val != null)
{
try
{
IAlgorithm alg = (IAlgorithm)curr.ItemTask.Item;
if (prob)
alg.Problem.Parameters[name].ActualValue = (IItem)val;
else
{
alg.Parameters[name].ActualValue = (IItem)val;
}
Clients.Caller.saveComplete("Parameter saved for " + name);
}
catch (NullReferenceException e)
{
Console.WriteLine("NullRefException: " + name + " - " + type);
}
catch (TargetException e)
{
Console.WriteLine("TargetException: " + name + " - " + type);
}
catch (NotSupportedException e)
{
Clients.Caller.createAlert("Parameter " + name + " could not be changed for it is a fixed parameter. All changes done in this view are not saved to Hive.", "danger");
}
}
else
Clients.Caller.createAlert("Format wrong for " + name + " of type " + type + ". Make sure you follow the right format pattern.", "warning");
}
}
}
}