public CuePrompter(MachineLearningActivity <T> .IMachineLearningActivity parentActivity) { Current = parentActivity; //cueEffect = new Effect("Cue sound", Resource.Raw._215028_shing); }
public MlrnCuePrompter(MachineLearningActivity <T> parentActivity) : base(parentActivity) { Current = parentActivity; }
//public static FieldState CannotAddNewClass = FieldState.Def("Add", false); //public static FieldState CanAddNewClass = FieldState.Def("Add", true); //public static FieldState RemoveClass = FieldState.Def("Remove", true); public void Update <T>(MachineLearningActivity <T> activity) where T : struct { // Silently fail if uninitialized (happens particularly during initialization of properties like Dataset) if (Save == null) { return; } // Prep easily-understood locals var Dataset = activity.Dataset; var Classifier = activity.Classifier; // Anything for us to load? This (and only this) doesn't depend on the dataset existing at all. bool foundAtLeastOneDataset = false; var externalDir = parentActivity.GetExternalFilesDir(null).AbsoluteFile; var allFiles = externalDir.ListFiles().ToList(); if (allFiles.Any(f => f.Name.EndsWith("." + DataSet.FileExtension))) { foundAtLeastOneDataset = true; } while (!foundAtLeastOneDataset && allFiles.Any(f => f.IsDirectory)) { var subdir = allFiles.First(f => f.IsDirectory); allFiles.Remove(subdir); var subfiles = subdir.ListFiles().Select(f => f.AbsoluteFile); if (subfiles.Any(f => f.Name.EndsWith("." + DataSet.FileExtension) || f.Name.EndsWith("." + Classifier.FileExtension))) { foundAtLeastOneDataset = true; break; } allFiles.AddRange(subfiles); } //Log.Debug("FileDirTest", $"Files: {allFiles.Select(f => f.Name).Join()}"); //foreach (File f in allFiles) // if (f.Name.EndsWith("." + DataSet.FileExtension)) Log.Debug("FileDirTest", $"Including dataset {f.Name}"); if (foundAtLeastOneDataset) { Load.State = CanLoad; } else { Load.State = CannotLoad; } if (_guessAndTeach != null) { _guessAndTeach.Enabled = (Classifier != null && Classifier.MachineOnline); } if (_cuemode != null) { _cuemode.Enabled = (Classifier != null && Classifier.MachineOnline); _gimmeCue.Visibility = _repeatCuesCheckbox.Visibility = _advancedCuesCheckbox.Visibility = (_cuemode.Checked) ? ViewStates.Visible : ViewStates.Gone; } _newClassName.Text = _newClassName.Text + ""; // Causes it to reassess its "on text changed" event // Rapid exit if there is no dataset at all, since the rest of this would be gibberish and throw lots of exceptions. if (Dataset == null) { Save.State = CannotSave; Clear.State = NothingToClear; Compute.State = CannotCompute; ComputeSingle.State = CannotComputeSingle; _listview.RequestLayout(); return; } // Reference conditions needed through the rest of this process bool HasBeenNamed = Dataset.NameIsUserChosen; bool HasClasses = Dataset.Classes != null && Dataset.Classes.Count > 0; bool HasSamples = Dataset.Samples != null && Dataset.Samples.Count > 0; bool HasNewSamples = Dataset.Samples.Any(s => !s.HasContributedToClassifier); bool DatasetHasChanged = Dataset.HasChanged; Dataset.HasChanged = false; // The "has changed" is "compared to the last time we ran ButtonStates.Update()", so now it's false by definition. // ======== Condition logic =========== // Does the dataset have a name? if (HasBeenNamed) { DatasetName.State = FieldState.Def(Dataset.Name, true); } else { DatasetName.State = FieldState.Def(null, true); DatasetName.Target.Hint = Dataset.Name; if (Dataset.SavedAsName != null) { if (Dataset.SavedAsName.Contains('/')) { int startIndex = Dataset.SavedAsName.LastIndexOf('/') + 1; int length = Dataset.SavedAsName.Length - startIndex - DataSet.FileExtension.Length - 1; if (length > 0) { DatasetName.Target.Hint = Dataset.SavedAsName.Substring(startIndex, length); } } else { DatasetName.Target.Hint = Dataset.SavedAsName.Substring(0, Dataset.SavedAsName.Length - DataSet.FileExtension.Length - 1); } } } // Is it empty but for (possibly) a name? if (!HasClasses) { Save.State = CannotSave; Compute.State = CannotCompute; ComputeSingle.State = CannotComputeSingle; if (HasBeenNamed || Dataset.SavedAsName != null) { Clear.State = IsClearedExceptName; } else { Clear.State = NothingToClear; } } // Does it contain classes, but no actual sample data yet? else if (!HasSamples) { Save.State = (DatasetHasChanged) ? CanSave : CannotSave; // Allowed to still save even if all it includes is empty gesture classes. Compute.State = CannotCompute; ComputeSingle.State = CannotComputeSingle; Clear.State = CanClear; } // Okay, so it contains meaningful content. What kind? else { Save.State = CanSave; // Note that the case where it has neither new data, nor already analyzed data, is handled above (since it therefore has NO data at all). // Maybe it's got new data but never been analyzed... if (HasNewSamples && !Classifier.MachineOnline) { Compute.State = (Dataset.Classes.Count > 1) ? CanCompute : CannotCompute; ComputeSingle.State = (Dataset.Classes.Count > 1) ? CanComputeSingle : CannotComputeSingle; Clear.State = CanClear; } // Or maybe it's got existing data and a classifier, but no new data... else if (!HasNewSamples && Classifier.MachineOnline) { Compute.State = JustComputed; ComputeSingle.State = JustComputed; Clear.State = CanClear; } // Or, lastly, maybe it's got both existing data and a classifier to go with them, AND some new data... else if (HasNewSamples && Classifier.MachineOnline) { Compute.State = CanRecompute; ComputeSingle.State = CanRecompute; Clear.State = CanClearNewData; } } //// Lastly, request an update of the list of gesture classes so that their data is up to date as well. //_listview.RequestLayout(); // Not sure whether this, or Invalidate(), is the more appropriate. //_listview.Invalidate(); //parentActivity.RunOnUiThread(() => //{ // _listview.RequestLayout(); // _listview.Invalidate(); // parentActivity.FindViewById(Resource.Id.mlrn_latest_sample_display).Invalidate(); //}); ((MachineLearningActivity <T> .IMachineLearningActivity)parentActivity).SetUpAdapters(Dataset); }