рефакторинг серверной части сапфора.

This commit is contained in:
2023-12-16 03:57:01 +03:00
parent b7b41ae59c
commit 34c08e7d44
32 changed files with 942 additions and 355 deletions

View File

@@ -0,0 +1,44 @@
package Visual_DVM_2021.Passes;
import Common.Current;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
import TestingSystem.Common.TestingPackage.TestingPackage;
import TestingSystem.Common.TestingPackageToKill.TestingPackageToKill;
import Visual_DVM_2021.Passes.Server.TestingSystemPass;
public abstract class AbortTestingPackage extends TestingSystemPass<TestingPackage> {
TestingPackageToKill packageToKill = null;
@Override
public String getIconPath() {
return "/icons/Ban.PNG";
}
@Override
public String getButtonText() {
return "";
}
public abstract Current currentName();
public abstract int getAbortType();
@Override
protected boolean canStart(Object... args) throws Exception {
packageToKill = null;
if (Current.Check(Log, currentName())) {
target = (TestingPackage) Current.get(currentName());
switch (target.state) {
case Done:
case Aborted:
Log.Writeln_("Пакет уже завершен.");
break;
default:
packageToKill = new TestingPackageToKill();
packageToKill.packageId = target.id;
packageToKill.type = getAbortType();
return true;
}
}
;
return false;
}
@Override
protected void ServerAction() throws Exception {
Command(new ServerExchangeUnit_2021(ServerCode.PublishObject, null, packageToKill));
}
}

View File

@@ -0,0 +1,55 @@
package Visual_DVM_2021.Passes;
import Common.Database.iDBTable;
import Common.Global;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
import TestingSystem.Common.TestingPackage.TestingPackage;
import Visual_DVM_2021.Passes.Server.TestingSystemPass;
import javafx.util.Pair;
import java.util.Vector;
public abstract class ActualizeTestingPackages<P extends TestingPackage> extends TestingSystemPass<Vector<Pair<Integer, Long>>> {
Class p;
public ActualizeTestingPackages(Class<P> p_in) {
p = p_in;
}
iDBTable<P> getTable() {
return (iDBTable<P>) Global.testingServer.db.tables.get(p);
}
protected abstract ServerCode getCheckCode();
@Override
protected boolean needsAnimation() {
return false;
}
@Override
protected boolean canStart(Object... args) throws Exception {
target = new Vector<>();
System.out.println("active packages");
for (P testingPackage : getTable().Data.values()) {
System.out.println(testingPackage.id + " " + testingPackage.state);
if (testingPackage.state.isActive()) {
System.out.println(testingPackage.state);
target.add(new Pair(testingPackage.id, testingPackage.ChangeDate));
System.out.println(testingPackage.id);
}
}
System.out.println("found " + target.size());
return !target.isEmpty();
}
@Override
protected void ServerAction() throws Exception {
Command(new ServerExchangeUnit_2021(getCheckCode(), "", target));
}
@Override
protected void performDone() throws Exception {
Vector<P> res = (Vector<P>) response.object;
Global.testingServer.db.BeginTransaction();
for (P actual : res)
Global.testingServer.db.UpdateWithCheck(actual);
Global.testingServer.db.Commit();
}
@Override
protected void showDone() throws Exception {
getTable().ShowUI(); ///RefreshUI()
}
}

View File

@@ -5,37 +5,15 @@ import Repository.Server.ServerExchangeUnit_2021;
import TestingSystem.Common.TasksPackageToKill.TasksPackageToKill;
import TestingSystem.Common.TestingPackageToKill.TestingPackageToKill;
import TestingSystem.DVM.DVMPackage.DVMPackage;
import Visual_DVM_2021.Passes.AbortTestingPackage;
import Visual_DVM_2021.Passes.Server.TestingSystemPass;
public class AbortDVMPackage extends TestingSystemPass<DVMPackage> {
TestingPackageToKill packageToKill = null;
public class AbortDVMPackage extends AbortTestingPackage {
@Override
public String getIconPath() {
return "/icons/Ban.PNG";
public Current currentName() {
return Current.DVMPackage;
}
@Override
public String getButtonText() {
return "";
}
@Override
protected boolean canStart(Object... args) throws Exception {
packageToKill = null;
if (Current.Check(Log, Current.DVMPackage)) {
target = Current.getDVMPackage();
switch (target.state) {
case Done:
case Aborted:
Log.Writeln_("Пакет уже завершен.");
break;
default:
packageToKill = new TestingPackageToKill(target);
return true;
}
}
;
return false;
}
@Override
protected void ServerAction() throws Exception {
Command(new ServerExchangeUnit_2021(ServerCode.PublishObject, null, packageToKill));
public int getAbortType() {
return 0;
}
}

View File

@@ -0,0 +1,13 @@
package Visual_DVM_2021.Passes.All;
import Common.Current;
import Visual_DVM_2021.Passes.AbortTestingPackage;
public class AbortSapforPackage extends AbortTestingPackage {
@Override
public Current currentName() {
return Current.SapforPackage;
}
@Override
public int getAbortType() {
return 1;
}
}

View File

@@ -1,46 +1,13 @@
package Visual_DVM_2021.Passes.All;
import Common.Global;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
import TestingSystem.DVM.DVMPackage.DVMPackage;
import Visual_DVM_2021.Passes.Server.TestingSystemPass;
import javafx.util.Pair;
import java.util.Vector;
public class ActualizeDVMPackages extends TestingSystemPass<Vector<Pair<Integer, Long>>> {
@Override
protected boolean needsAnimation() {
return false;
import Visual_DVM_2021.Passes.ActualizeTestingPackages;
public class ActualizeDVMPackages extends ActualizeTestingPackages<DVMPackage> {
public ActualizeDVMPackages() {
super(DVMPackage.class);
}
@Override
protected boolean canStart(Object... args) throws Exception {
target = new Vector<>();
System.out.println("active packages");
for (DVMPackage dvmPackage : Global.testingServer.db.dvmPackages.Data.values()) {
System.out.println(dvmPackage.id + " " + dvmPackage.state);
if (dvmPackage.state.isActive()) {
System.out.println(dvmPackage.state);
target.add(new Pair(dvmPackage.id, dvmPackage.ChangeDate));
System.out.println(dvmPackage.id);
}
}
System.out.println("found " + target.size());
return !target.isEmpty();
}
@Override
protected void ServerAction() throws Exception {
Command(new ServerExchangeUnit_2021(ServerCode.UpdateActiveDVMPackages, "", target));
}
@Override
protected void performDone() throws Exception {
Vector<DVMPackage> res = (Vector<DVMPackage>) response.object;
Global.testingServer.db.BeginTransaction();
for (DVMPackage actual : res)
Global.testingServer.db.UpdateWithCheck(actual);
Global.testingServer.db.Commit();
}
@Override
protected void showDone() throws Exception {
Global.testingServer.db.dvmPackages.ShowUI(); ///RefreshUI()
protected ServerCode getCheckCode() {
return ServerCode.UpdateActiveDVMPackages;
}
}

View File

@@ -9,6 +9,6 @@ public class ActualizePackages extends Pass_2021 {
@Override
protected void body() throws Exception {
passes.get(PassCode_2021.ActualizeDVMPackages).Do();
// passes.get(PassCode_2021.ActualizeSAPFORPackages).Do();
passes.get(PassCode_2021.ActualizeSapforPackages).Do();
}
}

View File

@@ -1,55 +0,0 @@
package Visual_DVM_2021.Passes.All;
import Common.Current;
import Common.Global;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
import TestingSystem.DVM.Tasks.TestRunTask;
import TestingSystem.DVM.TasksPackage.TasksPackage;
import TestingSystem.DVM.TasksPackage.TasksPackageState;
import TestingSystem.SAPFOR.SapforTask.SapforTask;
import TestingSystem.SAPFOR.SapforTasksPackage.SapforTasksPackage;
import Visual_DVM_2021.Passes.Server.TestingSystemPass;
import javafx.util.Pair;
import java.util.Vector;
public class ActualizeSAPFORPackages extends TestingSystemPass<Vector<Pair<Long, TasksPackageState>>> {
@Override
protected boolean needsAnimation() {
return false;
}
@Override
protected boolean canStart(Object... args) throws Exception {
target = new Vector<>();
for (SapforTasksPackage tasksPackage : Global.testingServer.account_db.sapforTasksPackages.Data.values()) {
if (tasksPackage.state.isActive())
target.add(new Pair<>(tasksPackage.id, tasksPackage.state));
}
return !target.isEmpty();
}
@Override
protected void ServerAction() throws Exception {
Command(new ServerExchangeUnit_2021(ServerCode.ActualizeSAPFORPackages, Current.getAccount().email, target));
}
@Override
protected void performDone() throws Exception {
int i = 0;
Vector<Pair<SapforTasksPackage, Vector<SapforTask>>> res = (Vector<Pair<SapforTasksPackage, Vector<SapforTask>>>) response.object;
Global.testingServer.account_db.BeginTransaction();
for (Pair<SapforTasksPackage, Vector<SapforTask>> pair : res) {
SapforTasksPackage tasksPackage = pair.getKey();
Global.testingServer.account_db.UpdateWithCheck(tasksPackage);
if (tasksPackage.state.equals(TasksPackageState.Done)) {
++i;
for (SapforTask task : pair.getValue()) {
Global.testingServer.account_db.UpdateWithCheck(task);
}
}
}
Global.testingServer.account_db.Commit();
}
@Override
protected void showDone() throws Exception {
Global.testingServer.account_db.sapforTasksPackages.RefreshUI();
Global.testingServer.account_db.sapforTasks.ShowUI();
}
}

View File

@@ -0,0 +1,13 @@
package Visual_DVM_2021.Passes.All;
import Repository.Server.ServerCode;
import TestingSystem.SAPFOR.SapforPackage.SapforPackage;
import Visual_DVM_2021.Passes.ActualizeTestingPackages;
public class ActualizeSapforPackages extends ActualizeTestingPackages<SapforPackage> {
public ActualizeSapforPackages() {
super(SapforPackage.class);
}
@Override
protected ServerCode getCheckCode() {
return ServerCode.UpdateActiveSapforPackages;
}
}

View File

@@ -1,4 +1,253 @@
package Visual_DVM_2021.Passes.All;
import Visual_DVM_2021.Passes.Pass_2021;
public class AddSapforPackage extends Pass_2021 {
}
import Common.Constants;
import Common.Current;
import Common.Database.Database;
import Common.Global;
import Common.UI.UI;
import Common.Utils.Index;
import ProjectData.LanguageName;
import TestingSystem.Common.Group.Group;
import TestingSystem.Common.Test.Test;
import TestingSystem.DVM.TasksPackage.TasksPackageState;
import TestingSystem.SAPFOR.Json.SapforConfiguration_json;
import TestingSystem.SAPFOR.Json.SapforTasksPackage_json;
import TestingSystem.SAPFOR.Json.SapforTest_json;
import TestingSystem.SAPFOR.SapforConfiguration.SapforConfiguration;
import TestingSystem.SAPFOR.SapforConfigurationCommand.SapforConfigurationCommand;
import TestingSystem.SAPFOR.SapforPackage.SapforPackage;
import Visual_DVM_2021.Passes.AddObjectPass;
import Visual_DVM_2021.Passes.PassCode_2021;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Vector;
public class AddSapforPackage extends AddObjectPass<SapforPackage> {
//--
protected int allTasksCount = 0;
protected LinkedHashMap<Integer, Vector<Integer>> groupsTests = null;
protected LinkedHashMap<String, Test> testsByDescriptions = null;
protected Vector<String> testsNames_lower = null; //все тесты что участвуют здесь
protected Vector<LanguageName> groupsLanguages = null;
protected Vector<String> testsIds = null;
protected Vector<String> configurationsIds = null;
protected File sapfor = null;
//---
protected boolean checkTestName(Test test) {
String name = test.description.toLowerCase();
if (testsNames_lower.contains(name)) {
Log.Writeln_("В пакет не могут входить тесты с одинаковыми именами (без учета регистра):" + test.description.toLowerCase());
return false;
}
testsNames_lower.add(name);
return true;
}
protected boolean getGroupTests(int groupId) {
Vector<Integer> groupTests = new Vector<>();
Vector<Integer> selectedGroupTests = new Vector<>();
//---
for (Test test : Global.testingServer.db.tests.Data.values()) {
if (test.group_id==groupId) {
groupTests.add(test.id);
if (test.isSelected())
selectedGroupTests.add(test.id);
}
}
if (!groupTests.isEmpty() && !selectedGroupTests.isEmpty())
groupTests = selectedGroupTests;
//---
if (groupTests.isEmpty()) {
Log.Writeln_("Пустая группа тестов: " + groupId);
return false;
}
//--
for (int testId : groupTests) {
Test test = Global.testingServer.db.tests.get(testId);
if (!checkTestName(test))
return false;
else
testsByDescriptions.put(test.description, test);
}
//--
groupsTests.put(groupId, groupTests);
//--
return true;
}
boolean checkTerminalCode(SapforConfiguration sapforConfiguration, PassCode_2021 code, int count, Vector<PassCode_2021> codes) {
if (count > 2) {
Log.Writeln_("Неверная конфигурация:" + sapforConfiguration.id + ": " +
code.getDescription() +
" возможно только один раз.");
return false;
}
//--
if ((count == 1) && codes.size() > 1) {
if (!codes.lastElement().equals(code)) {
Log.Writeln_("Неверная конфигурация:" + sapforConfiguration.id + ": " +
code.getDescription() +
" может быть только завершающей командой!");
return false;
}
}
return true;
}
public boolean getConfigurationCommands(SapforConfiguration sapforConfiguration) {
//1. получить список всех команд.
Vector<PassCode_2021> codes = new Vector<>();
//-- счетчик завершающих команд.
LinkedHashMap<PassCode_2021, Index> terminalCodesCount = new LinkedHashMap<>();
for (PassCode_2021 code : Constants.terminalSapforTestingCodes)
terminalCodesCount.put(code, new Index());
//--
for (SapforConfigurationCommand command : Global.testingServer.db.sapforConfigurationCommands.Data.values()) {
if (command.sapforconfiguration_id==sapforConfiguration.id) {
codes.add(command.passCode);
//---
for (PassCode_2021 t_code : Constants.terminalSapforTestingCodes) {
if (command.passCode.equals(t_code))
terminalCodesCount.get(t_code).Inc();
}
//---
}
}
//--
if (codes.size() == 0) {
Log.Writeln_("Пустая конфигурация:" + sapforConfiguration.id);
return false;
}
for (PassCode_2021 t_code : Constants.terminalSapforTestingCodes) {
if (!checkTerminalCode(sapforConfiguration, t_code,
terminalCodesCount.get(t_code).getValue(), codes
))
return false;
}
//--
return true;
}
//временный вариант. в дальнейшем, следует сделать возможность формирования.(?)
public AddSapforPackage() {
super(SapforPackage.class);
}
@Override
protected Database getDb() {
return Global.testingServer.db;
}
@Override
protected boolean canStart(Object... args) throws Exception {
if (!Current.getAccount().CheckRegistered(Log)) {
return false;
}
if (Current.Check(Log, Current.ServerSapfor)) {
for (SapforPackage sapforPackage : Global.testingServer.db.sapforPackages.Data.values()) {
if (sapforPackage.state.equals(TasksPackageState.Draft)) {
Log.Writeln_("Может существовать только один пакет, готовящийся к публикации.");
return false;
}
}
//--
allTasksCount = 0;
groupsTests = new LinkedHashMap<>();
testsNames_lower = new Vector<>();
testsByDescriptions = new LinkedHashMap<>();
groupsLanguages = new Vector<>();
testsIds =new Vector<>();
configurationsIds = new Vector<>();
//--
if (Global.testingServer.db.sapforConfigurations.getCheckedCount() == 0) {
Log.Writeln_("Не отмечено ни одной конфигурации SAPFOR.");
return false;
}
//-
for (SapforConfiguration configuration : Global.testingServer.db.sapforConfigurations.getCheckedItems()) {
if (!getConfigurationCommands(configuration))
return false;
}
//--
if (Global.testingServer.db.groups.getCheckedCount() == 0) {
Log.Writeln_("Не отмечено ни одной группы тестов");
return false;
}
//--
for (Group group : Global.testingServer.db.groups.getCheckedItems()) {
//---
if (!groupsLanguages.contains(group.language))
groupsLanguages.add(group.language);
//-
if (groupsLanguages.get(0) != LanguageName.fortran) {
Log.Writeln_("Поддерживается пакетный режим только для языка Fortran!");
return false;
}
if (groupsLanguages.size() > 1) {
Log.Writeln_("Запуск тестов на разных языках в рамках одного пакета запрещен!");
return false;
}
//---
if (!getGroupTests(group.id))
return false;
}
//--
for (int i = 0; i < Global.testingServer.db.sapforConfigurations.getCheckedCount(); ++i) {
for (Vector<Integer> tests : groupsTests.values())
allTasksCount += tests.size();
}
//--
for (Test test : testsByDescriptions.values())
testsIds.add(String.valueOf(test.id));
//--
for (SapforConfiguration configuration : Global.testingServer.db.sapforConfigurations.getCheckedItems())
configurationsIds.add(String.valueOf(configuration.id));
//--
target = new SapforPackage();
target.id = Constants.Nan;
//-
target.sender_name = Current.getAccount().name;
target.sender_address = Current.getAccount().email;
//-
target.drv = Current.getServerSapfor().call_command;
target.version = Current.getServerSapfor().version;
target.kernels = Global.properties.TestingKernels;
target.needsEmail = Global.properties.EmailOnTestingProgress ? 1 : 0;
//--
target.tasksCount = allTasksCount;
target.testsIds = String.join("\n", testsIds);
target.configurationsIds = String.join("\n", configurationsIds);
//--
target.sapforId = Current.getServerSapfor().id;
target.testsNames = String.join(";", testsNames_lower);
//
SapforTasksPackage_json package_json = new SapforTasksPackage_json();
target.package_json = package_json;
///-------------------------------
package_json.kernels = target.kernels;
for (Test test : testsByDescriptions.values()) {
SapforTest_json test_json = new SapforTest_json();
test_json.id = test.id;
test_json.description = test.description;
test_json.group_description = Global.testingServer.db.groups.get(test.group_id).description;
package_json.tests.add(test_json);
}
///-------------------------------
for (SapforConfiguration configuration : Global.testingServer.db.sapforConfigurations.getCheckedItems()) {
//--
SapforConfiguration_json configuration_json = new SapforConfiguration_json();
configuration_json.id = configuration.id;
configuration_json.flags = configuration.getFlags();
configuration_json.codes.add(PassCode_2021.SPF_CorrectCodeStylePass); //всегда добавляется.
configuration_json.codes.addAll(configuration.getPassCodes());
//--->>
package_json.configurations.add(configuration_json);
//-->>
}
package_json.sapfor_drv = Current.getServerSapfor().call_command;
///-------------------------------
return (UI.Question("Будет добавлено:\n"
+ allTasksCount + " задач\n" +
"Продолжить"));
}
return false;
}
@Override
protected void body() throws Exception {
//черновик не вставляется в бд. идет только как элемент списка.
Global.testingServer.db.sapforPackages.Data.put(target.id, target);
}
}

View File

@@ -0,0 +1,8 @@
package Visual_DVM_2021.Passes.All;
import TestingSystem.SAPFOR.SapforPackage.SapforPackage;
import Visual_DVM_2021.Passes.DeleteTestingPackages;
public class DeleteSapforPackage extends DeleteTestingPackages<SapforPackage> {
public DeleteSapforPackage() {
super(SapforPackage.class);
}
}

View File

@@ -1,46 +1,13 @@
package Visual_DVM_2021.Passes.All;
import Common.Current;
import Common.Global;
import Common.UI.UI;
import Common.Utils.Utils;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
import TestingSystem.Common.TestingServer;
import TestingSystem.DVM.DVMPackage.DVMPackage;
import TestingSystem.DVM.TasksPackage.TasksPackageState;
import Visual_DVM_2021.Passes.Server.PublishServerObject;
import javafx.util.Pair;
public class StartDVMPackage extends PublishServerObject<TestingServer, DVMPackage>{
import Visual_DVM_2021.Passes.StartTestingPackage;
public class StartDVMPackage extends StartTestingPackage<DVMPackage> {
public StartDVMPackage() {
super(Global.testingServer, DVMPackage.class);
super(DVMPackage.class);
}
@Override
protected int getTimeout() {
return 0;
}
@Override
public String getIconPath() {
return "/icons/Start.png";
}
@Override
protected boolean canStart(Object... args) throws Exception {
if (!Current.getAccount().CheckRegistered(Log)) {
return false;
}
if (Current.Check(Log, Current.DVMPackage)) {
target = Current.getDVMPackage();
//-
if (target.tasksCount == 0) {
Log.Writeln_("В пакете отсутствуют задачи.");
return false;
}
if (UI.Question("Будет запущено:\n"
+target.tasksCount + " задач на запуск.\n" +
"Продолжить")) {
target.state = TasksPackageState.Queued;
return true;
}
}
return false;
protected Current getCurrentName() {
return Current.DVMPackage;
}
}

View File

@@ -0,0 +1,13 @@
package Visual_DVM_2021.Passes.All;
import Common.Current;
import TestingSystem.SAPFOR.SapforPackage.SapforPackage;
import Visual_DVM_2021.Passes.StartTestingPackage;
public class StartSapforPackage extends StartTestingPackage<SapforPackage> {
public StartSapforPackage() {
super(SapforPackage.class);
}
@Override
protected Current getCurrentName() {
return Current.SapforPackage;
}
}

View File

@@ -204,7 +204,6 @@ public class StartSapforTests extends PublishServerAccountObject<SapforTasksPack
target.state = TasksPackageState.Queued;
target.needsEmail = Global.properties.EmailOnTestingProgress ? 1 : 0;
//---
//--
return (UI.Question("Будет запущено:\n"
+ allTasksCount + " задач\n" +
"Продолжить"));

View File

@@ -306,7 +306,7 @@ public enum PassCode_2021 {
ExportTasksPackageToExcel,
//->
ActualizeDVMPackages,
ActualizeSAPFORPackages,
ActualizeSapforPackages,
ActualizePackages,
//->
AddDVMPackage,
@@ -316,12 +316,21 @@ public enum PassCode_2021 {
AbortDVMPackage,
//->
AddSapforPackage,
DeleteSapforPackage,
StartSapforPackage,
AbortSapforPackage,
//->
TestPass;
public String getDescription() {
switch (this) {
case Undefined:
return "?";
case AbortSapforPackage:
return "Прервать пакет тестирования SAPFOR";
case StartSapforPackage:
return "Запустить пакет задач SAPFOR";
case DeleteSapforPackage:
return "Удалить пакеты тестирования SAPFOR";
case AddSapforPackage:
return "Добавить пакет задач SAPFOR";
case AbortDVMPackage:
@@ -338,7 +347,7 @@ public enum PassCode_2021 {
return "Обновить пакеты задач";
case ActualizeDVMPackages:
return "Обновить пакеты тестирования DVM";
case ActualizeSAPFORPackages:
case ActualizeSapforPackages:
return "Обновить пакеты тестирования SAPFOR";
case ExportTasksPackageToExcel:
return "Экспорт пакета задач в Excel";

View File

@@ -0,0 +1,48 @@
package Visual_DVM_2021.Passes;
import Common.Current;
import Common.Global;
import Common.UI.UI;
import TestingSystem.Common.TestingPackage.TestingPackage;
import TestingSystem.Common.TestingServer;
import TestingSystem.DVM.TasksPackage.TasksPackageState;
import Visual_DVM_2021.Passes.Server.PublishServerObject;
public abstract class StartTestingPackage<P extends TestingPackage> extends PublishServerObject<TestingServer, P> {
public StartTestingPackage(Class<P> p_in) {
super(Global.testingServer, p_in);
}
@Override
protected int getTimeout() {
return 0;
}
@Override
public String getIconPath() {
return "/icons/Start.png";
}
protected abstract Current getCurrentName();
@Override
protected boolean canStart(Object... args) throws Exception {
if (!Current.getAccount().CheckRegistered(Log)) {
return false;
}
if (Current.Check(Log, getCurrentName())) {
target = (P) Current.get(getCurrentName());
//-
if (!target.state.equals(TasksPackageState.Draft)) {
Log.Writeln_("Возможно запустить только пакет, готовящийся к публикации!");
return false;
}
if (target.tasksCount == 0) {
Log.Writeln_("В пакете отсутствуют задачи.");
return false;
}
if (UI.Question("Будет запущено:\n"
+ target.tasksCount + " задач.\n" +
"Продолжить")) {
target.state = TasksPackageState.Queued;
return true;
}
}
return false;
}
}