/// <summary> /// This function is called by the trigger whenever /// this trigger has been TRIGGERED. /// </summary> /// <param name="current"> /// The current value of the targeted controller. /// </param> /// <param name="previous"> /// The previous value of the targeted controller. /// </param> /// <param name="difference"> /// The value difference of the targeted controller. /// </param> /// <param name="adjustedDifference"> /// The adjusted value difference of the targeted controller. /// This value is the difference value as if it took place over a /// certain time period, controlled by VisBaseController.mc_fTargetAdjustedDifferenceTime. The /// default of this essientially indicates a frame rate of 60 fps to determine /// the adjusted difference. This should be used for almost all difference /// calculations, as it is NOT frame rate dependent. /// </param> public override void OnTriggered(float current, float previous, float difference, float adjustedDifference) { Rigidbody rigidbodyComp = GetComponent <Rigidbody>(); if (rigidbodyComp != null) { //get normalized direction Vector3 normalDir = forceDirection.normalized; //get the source value float value = current; if (controllerValue == ControllerSourceValue.Previous) { value = previous; } else if (controllerValue == ControllerSourceValue.Difference) { value = adjustedDifference; } //calc the property value float forceValue = VisHelper.ConvertBetweenRanges(value, minControllerValue, maxControllerValue, minForceValue, maxForceValue, invertValue); //add force rigidbodyComp.AddForce(normalDir * forceValue, forceMode); } }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// //var chartQueryPieChartData = new Dictionary<string, long>(); var chartQueryResultsLocal = Queries.GetActivityPieChartData(_date); // merge with remote data if necessary //TODO: REMOTE DATA //chartQueryPieChartData = RemoteDataHandler.VisualizeWithRemoteData() // ? RemoteDataHandler.MergeActivityData(chartQueryResultsLocal, Queries.GetActivityPieChartData(_date)) // : chartQueryResultsLocal; ///////////////////// // data cleaning ///////////////////// //// remove IDLE (doesn't belong to activity on computer) //if (chartQueryResultsLocal.ContainsKey(Dict.Idle)) // chartQueryResultsLocal.Remove(Dict.Idle); // calculate total active time var totalHoursWorked = chartQueryResultsLocal.Sum(x => x.Value); // check if we have enough data if (chartQueryResultsLocal.Count == 0 || totalHoursWorked < _minTimeWorked) { html += VisHelper.NotEnoughData(Dict.NotEnoughData); return(html); } PrepareDataForVisualization(chartQueryResultsLocal); ///////////////////// // HTML ///////////////////// html += "<p style='text-align: center;'>Total hours worked on your computer: <strong>" + Math.Round(totalHoursWorked, 1) + "</strong>.</p>"; html += "<div id='" + VisHelper.CreateChartHtmlTitle(Title) + "' style='height:75%;' align='center'></div>"; ///////////////////// // JS ///////////////////// var columns = string.Empty; foreach (var program in chartQueryResultsLocal) { columns += string.Format(CultureInfo.InvariantCulture, "['{0}', {1}], ", program.Key, Math.Round(program.Value, 1)); } var data = "columns: [ " + columns + "], type: 'pie'"; html += "<script type='text/javascript'>"; html += "var " + VisHelper.CreateChartHtmlTitle(Title) + " = c3.generate({ bindto: '#" + VisHelper.CreateChartHtmlTitle(Title) + "', data: { " + data + "}, pie: { label: { format: function (value, ratio, id) { return value + 'h';}}}, padding: { top: 0, right: 0, bottom: 0, left: 0 }, legend: { show: true, position: 'bottom' }});"; html += "</script>"; return(html); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var queryResultsLocal = Queries.GetLongestFocusOnProgram(_date); var durInMin = (queryResultsLocal == null) ? 0 : queryResultsLocal.DurationInSec / 60.0; if (queryResultsLocal == null || durInMin <= _minFocusTime) { html += VisHelper.NotEnoughData(string.Format(CultureInfo.InvariantCulture, "We either don't have enough data or you didn't focus on a single program for more than {0} minutes on this day.", _minFocusTime)); return(html); } ///////////////////// // HTML ///////////////////// html += "<p style='text-align: center; margin-top:-0.7em;'><strong style='font-size:2.5em; color:" + Shared.Settings.RetrospectionColorHex + ";'>" + Math.Round(durInMin, 0) + "</strong> min</p>"; html += string.Format(CultureInfo.InvariantCulture, "<p style='text-align: center; margin-top:-0.7em;'>in {0}<br />from {1} to {2}</p>", ProcessNameHelper.GetFileDescription(queryResultsLocal.Process), queryResultsLocal.From.ToShortTimeString(), queryResultsLocal.To.ToShortTimeString()); return(html); }
/// <summary> /// This function is called by the base modifier whenever /// the value of the targeted controller is updated. /// </summary> /// <param name="current"> /// The current value of the targeted controller. /// </param> /// <param name="previous"> /// The previous value of the targeted controller. /// </param> /// <param name="difference"> /// The value difference of the targeted controller. /// </param> /// <param name="adjustedDifference"> /// The adjusted value difference of the targeted controller. /// This value is the difference value as if it took place over a /// certain time period, controlled by VisBaseController.mc_fTargetAdjustedDifferenceTime. The /// default of this essientially indicates a frame rate of 60 fps to determine /// the adjusted difference. This should be used for almost all difference /// calculations, as it is NOT frame rate dependent. /// </param> public override void OnValueUpdated(float current, float previous, float difference, float adjustedDifference) { //get the source value float value = current; if (controllerSourceValue == ControllerSourceValue.Previous) { value = previous; } else if (controllerSourceValue == ControllerSourceValue.Difference) { value = adjustedDifference; } //calc the property value float propertyValue = VisHelper.ConvertBetweenRanges(value, minControllerValue, maxControllerValue, minPropertyValue, maxPropertyValue, invertValue); //call to abstract function to set the property SetProperty(propertyValue); }
/// <summary> /// Creates a list of one-hour axis times /// </summary> /// <param name="date"></param> /// <returns></returns> private static string CalculateLineChartAxisTicks(DateTimeOffset date) { var dict = new Dictionary <DateTime, int>(); VisHelper.PrepareTimeAxis(date, dict, 60); return(dict.Aggregate("", (current, a) => current + (DateTimeHelper.JavascriptTimestampFromDateTime(a.Key) + ", ")).Trim().TrimEnd(',')); }
/// <summary> /// This is called when this component is started. /// </summary> public override void Start() { base.Start(); maxControllerValue = VisHelper.Validate(maxControllerValue, -1000000.0f, 1000000.0f, Defaults.maxControllerValue, this, "maxControllerValue", false); minControllerValue = VisHelper.Validate(minControllerValue, -1000000.0f, maxControllerValue, Mathf.Min(Defaults.minControllerValue, maxControllerValue), this, "minControllerValue", false); maxPropertyValue = VisHelper.Validate(maxPropertyValue, -1000000.0f, 1000000.0f, Defaults.maxPropertyValue, this, "maxPropertyValue", false); minPropertyValue = VisHelper.Validate(minPropertyValue, -1000000.0f, maxPropertyValue, Mathf.Min(Defaults.minPropertyValue, maxPropertyValue), this, "minPropertyValue", false); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var programUsePerDay = GetProgramUsePerDay(); var totalHoursPerDay = GetTotalHoursPerDay(programUsePerDay); if (programUsePerDay.Count < 1) { html += VisHelper.NotEnoughData(Dict.NotEnoughData); return(html); } ///////////////////// // HTML ///////////////////// html += string.Format(CultureInfo.InvariantCulture, "<table id='{0}'>", VisHelper.CreateChartHtmlTitle(Title)); html += GetTableHeader(); html += "<tbody style='overflow:hidden;'>"; foreach (var prog in programUsePerDay) { html += "<tr>"; html += "<td>" + prog.Key + "</td>"; for (int i = 1; i < 7; i++) { html += GetTableRow(GetPercentage(prog.Value.Days[i], totalHoursPerDay[i])); } html += GetTableRow(GetPercentage(prog.Value.Days[0], totalHoursPerDay[0])); // special case: to have Sunday last (TODO: make better, as it isn't the same in every culture) html += "</tr>"; } html += "</tbody>"; html += "</table>"; ///////////////////// // create & add javascript //////////////////// var js = "<script type='text/javascript'>" + "var tf = new TableFilter('" + VisHelper.CreateChartHtmlTitle(Title) + "', { base_path: '/', " + "col_widths:[ '9.6875em', '2.1875em', '2.1875em', '2.1875em', '2.1875em', '2.1875em', '2.1875em', '2.1875em'], " // fixed columns sizes + "col_0: 'none', col_1: 'none', col_2: 'none', col_3: 'none', col_4: 'none', col_5: 'none', col_6: 'none', col_7: 'none', " + "alternate_rows: true, " // styling options + "grid_layout: true, grid_width: '25.6em', grid_height: '18em', grid_cont_css_class: 'grd-main-cont', grid_tblHead_cont_css_class: 'grd-head-cont', " // styling & behavior of the table + "}); " // no content options + "tf.init(); " + "</script>"; html += " " + js; return(html); }
private static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("Arguments:"); Console.WriteLine("\t-c : Compile Main File"); Console.WriteLine("\t-clean : Clean Build Directory"); Console.WriteLine("\t-r : Run Dynamic Commandline"); Console.WriteLine("\t-o : Optimize Assembly"); Console.WriteLine("\t-d : Debug(Make all labels and data sections visible)"); return; } bool compile = args.Any(x => x == "-c"); bool clean = args.Any(x => x == "-clean"); bool run = args.Any(x => x == "-r"); bool optimized = args.Any(x => x == "-o"); bool debug = args.Any(x => x == "-d"); FirstSetup.Start(); LinkerSettings linkerSettings = SettingsManager.GetSettings <LinkerSettings>(); linkerSettings.NoHiddenItems = debug; SettingsManager.SaveSettings(linkerSettings); AssemblyGeneratorSettings gsettings = SettingsManager.GetSettings <AssemblyGeneratorSettings>(); gsettings.Format = "v1"; //Set Raw Assembly Mode SettingsManager.SaveSettings(gsettings); HlCompilerSettings settings = SettingsManager.GetSettings <HlCompilerSettings>(); settings.OptimizeAll = optimized; SettingsManager.SaveSettings(settings); string output = null; output = compile ? VisHelper.Compile(clean) : FirstSetup.DefaultFile; if (run) { if (output == null) { Console.WriteLine($"Output file error."); FirstSetup.End(EndOptions.Default); return; } ConsoleLoop(output); } FirstSetup.End(EndOptions.Default); }
/// <summary> /// This function is called when this trigger is started. /// Should be override by sub classes to initialize. /// </summary> public virtual void Start() { //make sure to restore the targets if needed VisManager.RestoreVisManagerTarget(this); VisBaseController.RestoreVisBaseControllerTarget(this); //validate trigger variables. triggerThreshold = VisHelper.Validate(triggerThreshold, 0.0001f, 10000.0f, Defaults.triggerThreshold, this, "triggerThreshold", false); triggerReactivateDelay = VisHelper.Validate(triggerReactivateDelay, 0.0f, 10000.0f, Defaults.triggerReactivateDelay, this, "triggerReactivateDelay", false); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var chartQueryResultsLocal = Queries.GetUserProductivityTimelineData(_date, VisType.Day); if (chartQueryResultsLocal.Count < 3) // 3 is the minimum number of input-data-items { html += VisHelper.NotEnoughData("It is not possible to give you insights into your productivity as you didn't fill out the pop-up often enough. Try to fill it out at least 3 times per day."); return(html); } ///////////////////// // CSS ///////////////////// html += "<style type='text/css'>"; html += ".c3-line { stroke-width: 2px; }"; html += ".c3-grid text, c3.grid line { fill: gray; }"; html += "</style>"; ///////////////////// // HTML ///////////////////// html += "<div id='" + VisHelper.CreateChartHtmlTitle(Title) + "' style='height:75%;' align='center'></div>"; html += "<p style='text-align: center; font-size: 0.66em;'>Hint: Interpolates your perceived productivity, based on your pop-up responses.</p>"; ///////////////////// // JS ///////////////////// var ticks = CalculateLineChartAxisTicks(_date); var timeAxis = chartQueryResultsLocal.Aggregate("", (current, a) => current + (DateTimeHelper.JavascriptTimestampFromDateTime(a.Item1) + ", ")).Trim().TrimEnd(','); var productivityFormattedData = chartQueryResultsLocal.Aggregate("", (current, p) => current + (p.Item2 + ", ")).Trim().TrimEnd(','); const string colors = "'User_Input_Level' : '" + Shared.Settings.RetrospectionColorHex + "'"; var data = "x: 'timeAxis', columns: [['timeAxis', " + timeAxis + "], ['Productivity', " + productivityFormattedData + " ] ], type: 'line', colors: { " + colors + " }, axis: { 'PerceivedProductivity': 'y' } "; // type options: spline, step, line var grid = "y: { lines: [ { value: 1, text: 'not at all productive' }, { value: 4, text: 'moderately productive' }, { value: 7, text: 'very productive' } ] } "; var axis = "x: { localtime: true, type: 'timeseries', tick: { values: [ " + ticks + "], format: function(x) { return formatDate(x.getHours()); }} }, y: { min: 1, max: 7 }"; // show: false, var tooltip = "show: true, format: { title: function(d) { return 'Pop-Up answered: ' + formatTime(d.getHours(),d.getMinutes()); }}"; var parameters = " bindto: '#" + VisHelper.CreateChartHtmlTitle(Title) + "', data: { " + data + " }, padding: { left: 15, right: 0, bottom: -10, top: 0}, legend: { show: false }, axis: { " + axis + " }, grid: { " + grid + " }, tooltip: { " + tooltip + " }, point: { show: true }"; html += "<script type='text/javascript'>"; html += "var formatDate = function(hours) { var suffix = 'AM'; if (hours >= 12) { suffix = 'PM'; hours = hours - 12; } if (hours == 0) { hours = 12; } if (hours < 10) return '0' + hours + ' ' + suffix; else return hours + ' ' + suffix; };"; html += "var formatTime = function(hours, minutes) { var minFormatted = minutes; if (minFormatted < 10) minFormatted = '0' + minFormatted; var suffix = 'AM'; if (hours >= 12) { suffix = 'PM'; hours = hours - 12; } if (hours == 0) { hours = 12; } if (hours < 10) return '0' + hours + ':' + minFormatted + ' ' + suffix; else return hours + ':' + minFormatted + ' ' + suffix; };"; html += "var " + VisHelper.CreateChartHtmlTitle(Title) + " = c3.generate({ " + parameters + " });"; // return x.getHours() + ':' + x.getMinutes(); html += "</script>"; return(html); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var orderedTimelineList = Queries.GetDayWindowTitleData(_date); ///////////////////// // data cleaning ///////////////////// // show message if not enough data var sum = orderedTimelineList.Sum(i => i.DurationInSeconds); if (orderedTimelineList.Count <= 3 || sum < 5 * 60) // 3 is the minimum number of input-data-items & 5 minutes of data { _sb.Append(VisHelper.NotEnoughData(Dict.NotEnoughData)); return(_sb.ToString()); } // remove first + last items if IDLE if (orderedTimelineList.First().ActivityCategory == ActivityCategory.Idle) { orderedTimelineList.Remove(orderedTimelineList.First()); } if (orderedTimelineList.Last().ActivityCategory == ActivityCategory.Idle) { orderedTimelineList.Remove(orderedTimelineList.Last()); } ///////////////////// // Create HTML ///////////////////// _sb.Append(GetActivityVisualizationContent(orderedTimelineList)); return(_sb.ToString()); //var data = Queries.GetWindowTitles(30, _date); //foreach(List<string> list in data) //{ // foreach(string title in list) // { // html += title + " "; // } //} //return html; }
/// <summary> /// This function is called by the trigger whenever /// this trigger has been TRIGGERED. /// </summary> /// <param name="current"> /// The current value of the targeted controller. /// </param> /// <param name="previous"> /// The previous value of the targeted controller. /// </param> /// <param name="difference"> /// The value difference of the targeted controller. /// </param> /// <param name="adjustedDifference"> /// The adjusted value difference of the targeted controller. /// This value is the difference value as if it took place over a /// certain time period, controlled by VisBaseController.mc_fTargetAdjustedDifferenceTime. The /// default of this essientially indicates a frame rate of 60 fps to determine /// the adjusted difference. This should be used for almost all difference /// calculations, as it is NOT frame rate dependent. /// </param> public override void OnTriggered(float current, float previous, float difference, float adjustedDifference) { //check if this should be a random value if (randomValue) {//get random value m_fTargetPropertyValue = UnityEngine.Random.Range(minPropertyValue, maxPropertyValue); } else {//get value from ranges //get the source value float value = current; if (controllerSourceValue == ControllerSourceValue.Previous) { value = previous; } else if (controllerSourceValue == ControllerSourceValue.Difference) { value = adjustedDifference; } //calc the property value m_fTargetPropertyValue = VisHelper.ConvertBetweenRanges(value, minControllerValue, maxControllerValue, minPropertyValue, maxPropertyValue, invertValue); } //check if the value needs to be limited if (float.IsPositiveInfinity(m_fCurrentPropertyValue)) {//the current value is infinity, set instantly no matter what m_fCurrentPropertyValue = m_fTargetPropertyValue; SetProperty(m_fCurrentPropertyValue); } else if (limitIncreaseRate && m_fCurrentPropertyValue < m_fTargetPropertyValue) {//limit increase SetProperty(m_fCurrentPropertyValue); } else if (limitDecreaseRate && m_fCurrentPropertyValue > m_fTargetPropertyValue) {//limit decrease SetProperty(m_fCurrentPropertyValue); } else {//no limiting, set instantly m_fCurrentPropertyValue = m_fTargetPropertyValue; SetProperty(m_fCurrentPropertyValue); } }
private void Lbshapes_SelectionChanged(object _, SelectionChangedEventArgs scea) { spProperties.Children.Clear(); if (scea.AddedItems.Count == 0) { spProperties.Children.Add(new TextBlock() { Foreground = white, TextWrapping = TextWrapping.Wrap, Text = "Kein Element ausgewählt" }); return; } UIHelpers.VisualizationHelper.AddToSP(spProperties, VisHelper.VisualizeObject(scea.AddedItems[0])); }
/// <summary> /// This is called when this data group is started. /// </summary> public void Start() { //validate the boost and cutoff for this data group. boost = VisHelper.Validate(boost, 0.001f, 10000.0f, Defaults.boost, this, "boost", false); cutoff = VisHelper.Validate(cutoff, 0.001f, 10000.0f, Defaults.cutoff, this, "cutoff", false); //create all data containers for all data value types for (int i = 0; i < m_aoDataContainers.Length; i++) { m_aoDataContainers[i] = new VisDataContainer(); } //make sure there is a vis manager assigned to this data group if (m_oVisManager != null) { //validate the frequency values and number of sub data groups. frequencyRangeEndIndex = VisHelper.Validate(frequencyRangeEndIndex, 0, (int)m_oVisManager.windowSize, 0, this, "frequencyRangeEndIndex", true); frequencyRangeStartIndex = VisHelper.Validate(frequencyRangeStartIndex, 0, frequencyRangeEndIndex, 0, this, "frequencyRangeStartIndex", true); numberSubDataGroups = VisHelper.Validate(numberSubDataGroups, 1, (frequencyRangeEndIndex - frequencyRangeStartIndex) + 1, 1, this, "numberSubDataGroups", true); //create sub groups int range = (frequencyRangeEndIndex - frequencyRangeStartIndex) + 1; int increment = Mathf.RoundToInt(((float)range) / ((float)numberSubDataGroups)); if (increment <= 0) { increment = 1; } int remainder = range - (increment * (range / increment)); for (int i = frequencyRangeStartIndex; i <= frequencyRangeEndIndex - increment; i += increment) { //get the start and end index and create the sub group int startIndex = i; int endIndex = i; m_oSubDataGroups.Add(new VisSubDataGroup(startIndex, endIndex)); } //add the remainder onto the last sub group if (remainder > 0 && m_oSubDataGroups.Count > 0) { m_oSubDataGroups[m_oSubDataGroups.Count - 1].frequencyRangeEndIndex += remainder; } } else { //send warning that there is no vis manager. Debug.LogError("This data group must have an assigned VisManager."); } }
/// <summary> /// Creates a nice title depending on the setting /// </summary> /// <param name="visType"></param> /// <param name="date"></param> /// <returns></returns> private static string GetRetrospectionTitle(VisType visType, DateTimeOffset date) { switch (visType) { case VisType.Day: return("Your Retrospection for the " + date.Date.ToShortDateString()); case VisType.Week: return(string.Format(CultureInfo.InvariantCulture, "Your Retrospection for Week {0} ({1} - {2})", DateTimeHelper.GetWeekOfYear_Iso8601(date.Date), DateTimeHelper.GetFirstDayOfWeek_Iso8801(date.Date).Date.ToShortDateString(), DateTimeHelper.GetLastDayOfWeek_Iso8801(date.Date).Date.ToShortDateString())); } return(VisHelper.Error("Retrospection not supported!")); }
private string CreateDashboardItem(IVisualization vis, DateTimeOffset date) { try { var feedbackButtons = FeedbackThumbs.GetInstance().GetFeedbackThumbsUpDown(vis, date); var chartTitle = VisHelper.FormatChartTitle(vis.Title); var html = vis.GetHtml(); var itemTemplate = "<div class='item {3}'>{0}{1}{2}</div>"; return(string.Format(CultureInfo.InvariantCulture, itemTemplate, feedbackButtons, chartTitle, html, vis.Size)); } catch (Exception e) { Logger.WriteToLogFile(e); return(VisHelper.Error(string.Format(CultureInfo.InvariantCulture, "<div id='item {2}'>An error occurred when creating the visualization: '{0}'.</div>", vis.Title, vis.Size))); } }
/// <summary> /// Returns a dictionary with an input-level like data set for each interval (Settings.UserInputVisMinutesInterval) /// (new version, 2.0) /// </summary> /// <param name="date"></param> /// <returns></returns> internal static Dictionary <DateTime, int> GetUserInputTimelineData_v2(DateTimeOffset date) { var dto = new Dictionary <DateTime, int>(); // prepare Dictionary VisHelper.PrepareTimeAxis(date, dto, Settings.UserInputVisMinutesInterval); // get user input data (aggregate) try { var query = "SELECT tsStart, tsEnd, keyTotal, clickTotal, scrollDelta, movedDistance FROM " + Settings.DbTableUserInput_v2 + " WHERE STRFTIME('%s', DATE(time))==STRFTIME('%s', DATE('" + date.Date.ToString("u", CultureInfo.InvariantCulture) + "'));"; var table = Database.GetInstance().ExecuteReadQuery(query); foreach (DataRow row in table.Rows) { try { var time = DateTime.Parse((string)row["tsStart"], CultureInfo.InvariantCulture); time = time.AddSeconds(-time.Second); // nice seconds // find 10 minutes interval time = DateTimeHelper.RoundUp(time, TimeSpan.FromMinutes(Settings.UserInputVisMinutesInterval)); // add values if (dto.ContainsKey(time)) { var keystrokes = (long)row["keyTotal"]; var mouseClicks = (long)row["clickTotal"]; var mouseScrollDistance = (long)row["scrollDelta"]; var mouseMoves = (long)row["movedDistance"]; dto[time] += CalculateUserInputLevel(keystrokes, mouseClicks, mouseScrollDistance, mouseMoves); } } catch { } } table.Dispose(); } catch (Exception e) { Logger.WriteToLogFile(e); } return(dto); }
public override string GetHtml() { var html = string.Empty; List <Tuple <DateTime, int> > values = DatabaseConnector.GetStepsPerTimeFraction(DateTimeHelper.GetFirstDayOfWeek_Iso8801(_date), DateTimeHelper.GetLastDayOfWeek_Iso8801(_date), 24 * 60); if (values.Count <= 1) { html += VisHelper.NotEnoughData(); return(html); } //HTML html += "<div id='chart' height=20em, width=50em, style='align: center'></div>"; html += "<p style='text-align: center; font-size: 0.66em;'>Hint: Visualizes your steps per day. For more detailed information, visit: <a href='http://fitbit.com' target=_blank>fitbit.com</a>. (Last synced: " + DatabaseConnector.GetLastTimeSynced() + ").</p>"; return(html); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var workTimeData = GetWorkTimeData(); if (workTimeData.Where(i => i.Value.Item1 > 0).Count() < 1) { return(VisHelper.NotEnoughData()); } ///////////////////// // HTML ///////////////////// html += "<div id='" + VisHelper.CreateChartHtmlTitle(Title) + "' style='height:85%;' align='center'></div>"; ///////////////////// // JS ///////////////////// var totalTimespentData = workTimeData.Aggregate("", (current, p) => current + (Math.Round(p.Value.Item1, 1) + ", ")).Trim().TrimEnd(','); var timeSpentActiveData = workTimeData.Aggregate("", (current, p) => current + (Math.Round(p.Value.Item2, 1) + ", ")).Trim().TrimEnd(','); var formattedXAxis = workTimeData.Aggregate("", (current, p) => current + ("'" + DateTimeHelper.GetShortestDayName(p.Key) + "', ")).Trim().TrimEnd(','); var totalTimespentName = "at work in total (hours)"; var timeSpentActiveName = "active at the computer (hours)"; var data = "columns: [ ['" + totalTimespentName + "', " + totalTimespentData + "], ['" + timeSpentActiveName + "', " + timeSpentActiveData + "] ], type: 'bar' "; var bar = "width: { ratio: 0.5 }"; var colors = "'" + totalTimespentName + "' : '" + Shared.Settings.RetrospectionColorHex + "', '" + timeSpentActiveName + "' : '" + Shared.Settings.DarkGrayColorHex + "'"; var axis = "x: { type: 'category', categories: [ " + formattedXAxis + " ] }, y: { max: " + workTimeData.Max(i => i.Value.Item1) + " }"; var parameters = " bindto: '#" + VisHelper.CreateChartHtmlTitle(Title) + "', data: { " + data + " }, bar: { " + bar + " }, colors: { " + colors + " }, axis: { " + axis + " }, padding: { left: 20, right: 0, bottom: 0, top: 0}, grid: { y: { show: true } }, legend: { show: true } "; html += "<script type='text/javascript'>"; html += "var " + VisHelper.CreateChartHtmlTitle(Title) + " = c3.generate({ " + parameters + " });"; html += "</script>"; return(html); }
/// <summary> /// This function sets up this VisManager. /// </summary> public void Start() { //validate debug variables debugSpectrumBarWidth = VisHelper.Validate(debugSpectrumBarWidth, 1, 1000, Defaults.debugSpectrumBarWidth, this, "debugSpectrumBarWidth", false); debugSpectrumBarHeight = VisHelper.Validate(debugSpectrumBarHeight, 1, 1000, Defaults.debugSpectrumBarHeight, this, "debugSpectrumBarHeight", false); debugRawAudioBarHeight = VisHelper.Validate(debugRawAudioBarHeight, 1, 1000, Defaults.debugRawAudioBarHeight, this, "debugRawAudioBarHeight", false); debugDataGroupBarWidth = VisHelper.Validate(debugDataGroupBarWidth, 1, 1000, Defaults.debugDataGroupBarWidth, this, "debugDataGroupBarWidth", false); debugDataGroupBarHeight = VisHelper.Validate(debugDataGroupBarHeight, 1, 1000, Defaults.debugDataGroupBarHeight, this, "debugDataGroupBarHeight", false); debugControllerBarWidth = VisHelper.Validate(debugControllerBarWidth, 1, 1000, Defaults.debugControllerBarWidth, this, "debugControllerBarWidth", false); debugControllerBarHeight = VisHelper.Validate(debugControllerBarHeight, 1, 1000, Defaults.debugControllerBarHeight, this, "debugControllerBarHeight", false); debugSeparation = VisHelper.Validate(debugSeparation, 0, 1000, Defaults.debugSeparation, this, "debugSeparation", false); //Create the array to hold the audio data and initialize them m_afSpectrumData = new float[(int)windowSize]; m_afRawAudioData = new float[(int)windowSize]; m_afAuxiliaryData = new float[(int)windowSize]; for (int i = 0; i < (int)windowSize; i++) { m_afSpectrumData[i] = 0.0f; m_afRawAudioData[i] = 0.0f; m_afAuxiliaryData[i] = 0.0f; } //try to load 1x1white texture if (debugTexture == null) { debugTexture = (Texture)Resources.Load("1x1White"); } //Display a warning if no audio source was found. if (audioSource == null) { Debug.LogWarning("A VisManager should have an Audio Source assigned to it so it only listens to the specified music. " + "This manager will now default to using the static Audio Listener, which contains ALL audio playing " + "in the game. This Audio Listener does not work near as well as listening directly to an Audio Source, " + "so it is NOT recommended."); m_bUseAudioListener = true; } CalculateFrequencyResolution(); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var averageProductivityPerDay = GetAverageProductivityPerDay(); if (NotEnoughDataSets(averageProductivityPerDay)) { html += VisHelper.NotEnoughData("It is not possible to give you insights into your productivity as you didn't fill out the pop-up often enough or didn't work. Try to fill it out at least 3 times per day."); return(html); } ///////////////////// // HTML ///////////////////// html += "<div id='" + VisHelper.CreateChartHtmlTitle(Title) + "' style='height:80%;' align='center'></div>"; ///////////////////// // JS ///////////////////// var productivityFormattedData = averageProductivityPerDay.Aggregate("", (current, p) => current + (Math.Round(p.Value, 1) + ", ")).Trim().TrimEnd(','); var formattedXAxis = averageProductivityPerDay.Aggregate("", (current, p) => current + ("'" + DateTimeHelper.GetShortestDayName(p.Key) + "', ")).Trim().TrimEnd(','); var data = "columns: [ ['Average Productivity', " + productivityFormattedData + "] ], type: 'bar' "; var bar = "width: { ratio: 0.5 }"; var colors = "'Average Productivity' : '" + Shared.Settings.RetrospectionColorHex + "'"; var axis = "x: { type: 'category', categories: [ " + formattedXAxis + " ] }, y: { max: 7, min: 1, tick: { values: [ 1, 2, 3, 4, 5, 6, 7 ] } }"; var parameters = " bindto: '#" + VisHelper.CreateChartHtmlTitle(Title) + "', data: { " + data + " }, bar: { " + bar + " }, colors: { " + colors + " }, axis: { " + axis + " }, padding: { left: 20, right: 0, bottom: 0, top: 0}, grid: { y: { show: true } }, legend: { show: false } "; html += "<script type='text/javascript'>"; html += "var " + VisHelper.CreateChartHtmlTitle(Title) + " = c3.generate({ " + parameters + " });"; html += "</script>"; return(html); }
/// <summary> /// This is called when this component is started. /// </summary> public override void Start() { base.Start(); maxControllerValue = VisHelper.Validate(maxControllerValue, -1000000.0f, 1000000.0f, Defaults.maxControllerValue, this, "maxControllerValue", false); minControllerValue = VisHelper.Validate(minControllerValue, -1000000.0f, maxControllerValue, Mathf.Min(Defaults.minControllerValue, maxControllerValue), this, "minControllerValue", false); maxPropertyValue = VisHelper.Validate(maxPropertyValue, -1000000.0f, 1000000.0f, Defaults.maxPropertyValue, this, "maxPropertyValue", false); minPropertyValue = VisHelper.Validate(minPropertyValue, -1000000.0f, maxPropertyValue, Mathf.Min(Defaults.minPropertyValue, maxPropertyValue), this, "minPropertyValue", false); increaseRate = VisHelper.Validate(increaseRate, 0.00001f, 10000.0f, Defaults.increaseRate, this, "increaseRate", false); decreaseRate = VisHelper.Validate(decreaseRate, 0.00001f, 10000.0f, Defaults.decreaseRate, this, "decreaseRate", false); //check if return to rest is set if (returnToRest) { //make sure either limitting flag is checked if (!limitIncreaseRate && !limitDecreaseRate) {//warn and set to false Debug.LogWarning("If \"Return to Rest\" is true, you must have \"Limit Increase Rate\" or \"Limit Decrease Rate\" set to true. Resetting it to false!"); returnToRest = false; } } }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var orderedTimelineList = Queries.GetDayTimelineData(_date); ///////////////////// // data cleaning ///////////////////// // show message if not enough data if (orderedTimelineList.Count <= 3) // 3 is the minimum number of input-data-items { html += VisHelper.NotEnoughData(Dict.NotEnoughData); return(html); } // remove first + last items if IDLE if (orderedTimelineList.First().ActivityCategory == ActivityCategory.Idle) { orderedTimelineList.Remove(orderedTimelineList.First()); } if (orderedTimelineList.Last().ActivityCategory == ActivityCategory.Idle) { orderedTimelineList.Remove(orderedTimelineList.Last()); } ///////////////////// // Create HTML ///////////////////// html += GetActivityVisualizationContent(orderedTimelineList); return(html); }
private static void Main(string[] args) { bool compile = args.Any(x => x == "-c"); bool clean = args.Any(x => x == "-clean"); bool run = args.Any(x => x == "-r"); FirstSetup.Start(); string output = null; output = compile ? VisHelper.Compile(clean) : FirstSetup.DefaultFile; if (run) { if (output == null) { Console.WriteLine($"Output file '{output}' not found."); } VisHelper.Default(output).Run(); } FirstSetup.End(EndOptions.Default); }
public override string GetHtml() { var html = string.Empty; SleepVisualizationEntry value = DatabaseConnector.GetSleepDataForDay(DateTimeHelper.GetStartOfDay(_date), DateTimeHelper.GetEndOfDay(_date)); if (value == null) { html += VisHelper.NotEnoughData(); return(html); } //HTML html += "<div id='chart' style='align: center; font-size: 1.15em;'>"; html += "<p><b>Start:</b> " + value.StartTime.ToString(Settings.FORMAT_TIME) + "<span style='padding-left: 2em;'><b>End:</b> " + value.StartTime.AddMinutes(value.SleepDuration + value.AwakeDuration + value.RestlessDuration + value.AwakeAfterWakeUp).ToString(Settings.FORMAT_TIME) + "</span><span style='padding-left: 2em;'><b>Efficiency:</b> " + value.Efficiency + "%</span></p>"; html += "<p><b>Slept for:</b> " + DurationToTime(value.SleepDuration) + "</p>"; html += "<p><b>Time in bed after wakeup:</b> " + value.AwakeAfterWakeUp + " minutes</p>"; html += "<p><b>Awake:</b> " + value.AwakeCount + " time(s). (Total duration: " + value.AwakeDuration + " minutes" + ")</p>"; html += "<p><b>Restless:</b> " + value.RestlessCount + " time(s). (Total duration: " + value.RestlessDuration + " minutes" + ")</p>"; html += "</div>"; html += "<p style='text-align: center; font-size: 0.66em;'>Hint: Visualizes your sleep stats for the chosen day. For more detailed information,<br>visit: <a href='http://fitbit.com' target=_blank>fitbit.com</a>. (Last synced: " + DatabaseConnector.GetLastTimeSynced() + ").</p>"; return(html); }
public virtual string GetHtml() { return(VisHelper.Error("Not yet implemented")); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// // get the latest stored email entry var emailsSnapshotResult = Queries.GetEmailsSnapshot(_date.Date); var inbox = emailsSnapshotResult.Item2; var inboxUnread = emailsSnapshotResult.Item3; var sent = emailsSnapshotResult.Item4; var received = emailsSnapshotResult.Item5; var receivedUnread = emailsSnapshotResult.Item6; var isToday = (_date.Date == DateTime.Now.Date); var lastUpdatedMinsAgo = Math.Abs((DateTime.Now - emailsSnapshotResult.Item1).TotalMinutes); // if database entry is outdated or not there, create a live API call and override entries if (emailsSnapshotResult.Item1 == DateTime.MinValue || // no emails stored yet (isToday && lastUpdatedMinsAgo > Settings.SaveEmailCountsIntervalInMinutes)) // request is for today and saved results are too old // could not fetch sent emails { // create and save a new email snapshot (inbox, sent, received) var res = Queries.CreateEmailsSnapshot(_date.Date, false); inbox = res.Item1; inboxUnread = res.Item2; sent = res.Item3; received = res.Item4; receivedUnread = res.Item5; } // error (only if no data at all) if (sent < 0 && (received < 0 || receivedUnread < 0) && inbox < 0 && inboxUnread < 0) { return(VisHelper.NotEnoughData(Dict.NotEnoughData)); } // get averages over last 2 months var averagesSnapshot = Queries.GetEmailsSnapshotAverages(60); ///////////////////// // HTML ///////////////////// html += "<table>"; if (sent > -1) { html += "<tr><td><strong style='font-size:2.5em; color:#007acc;'>" + sent + "</strong></td><td>emails sent" + FormatAverage(sent, averagesSnapshot.Item3) + "</td></tr>"; } if (received > -1 && receivedUnread > -1) { html += "<tr><td><strong style='font-size:2.5em; color:#007acc;'>" + (received - receivedUnread) + "</strong></td><td>emails received that are read" + FormatAverage((received - receivedUnread), averagesSnapshot.Item4 - averagesSnapshot.Item5) + "</td></tr>"; } if (received > -1 && receivedUnread > -1) { html += "<tr><td><strong style='font-size:2.5em; color:#007acc;'>" + receivedUnread + "</strong></td><td>emails received that are unread" + FormatAverage(receivedUnread, averagesSnapshot.Item5) + "</td></tr>"; } if (inbox > -1) { html += "<tr><td><strong style='font-size:2.5em; color:#007acc;'>" + inbox + "</strong></td><td>emails in your inbox" + FormatAverage(inbox, averagesSnapshot.Item1) + "</td></tr>"; } if (inboxUnread > -1) { html += "<tr><td><strong style='font-size:2.5em; color:#007acc;'>" + inboxUnread + "</strong></td><td>unread emails in your inbox" + FormatAverage(inboxUnread, averagesSnapshot.Item2) + "</td></tr>"; } html += "</table>"; return(html); }
public override string GetHtml() { var html = string.Empty; //Get Data List <Tuple <DateTime, double, double> > values = DatabaseConnector.GetPolarValuesForDay(_date); if (values.Count <= 3) { html += VisHelper.NotEnoughData("It is not possible to give you insights because there is not enough biometric data available."); return(html); } // CSS html += "<style type='text/css'>"; html += ".c3-line { stroke-width: 2px; }"; html += ".c3-grid text, c3.grid line { fill: black; }"; html += ".axis path, .axis line {fill: none; stroke: black; stroke-width: 1; shape-rendering: crispEdges;}"; html += "</style>"; //HTML html += "<div id='chart' style='align: center'></div>"; html += "<p style='text-align: center; font-size: 0.66em;'>Hint: Visualizes your heart rate (HR) and your interbeat interval (RMSSD). (Last time synced with BLE device: " + DatabaseConnector.GetLastTimeSynced().ToString(CultureInfo.InstalledUICulture) + ")</p>"; //JS html += "<script>"; html += "var actualHeight = document.getElementsByClassName('item Wide')[0].offsetHeight;"; html += "var actualWidth = document.getElementsByClassName('item Wide')[0].offsetWidth;"; html += "var margin = {top: 30, right: 30, bottom: 30, left: 30}, width = (actualWidth * 0.97)- margin.left - margin.right, height = (actualHeight * 0.73) - margin.top - margin.bottom;"; html += "var parseDate = d3.time.format('%Y-%m-%d %H:%M').parse;"; html += GetDataAsJSString(values); html += "var x = d3.time.scale().range([0, width]);"; html += "var y0 = d3.scale.linear().range([height, 0]);"; html += "var y1 = d3.scale.linear().range([height, 0]);"; if (GetDurationInHours(values) >= 12) { html += "var xAxis = d3.svg.axis().scale(x).orient('bottom').ticks(d3.time.hours, 2).tickFormat(d3.time.format('%H:%M'));"; } else if (GetDurationInHours(values) > 3) { html += "var xAxis = d3.svg.axis().scale(x).orient('bottom').ticks(d3.time.hours, 1).tickFormat(d3.time.format('%H:%M'));"; } else { html += "var xAxis = d3.svg.axis().scale(x).orient('bottom').ticks(d3.time.minutes, 15).tickFormat(d3.time.format('%H:%M'));"; } html += "var yAxisLeft = d3.svg.axis().scale(y0).orient('left').ticks(5);"; html += "var yAxisRight = d3.svg.axis().scale(y1).orient('right').ticks(5);"; html += "var valueLine1 = d3.svg.line().interpolate('basis').defined(function(d) {return d.hr != null; }).x(function(d) {return x(d.ts); }).y(function(d) { return y0(d.hr); });"; html += "var valueLine2 = d3.svg.line().interpolate('basis').defined(function(d) {return d.rmssd != null; }).x(function(d) {return x(d.ts); }).y(function(d) { return y1(d.rmssd); });"; html += "var svg = d3.select('#chart').append('svg').attr('width', width + margin.left + margin.righ).attr('height', height + margin.top + margin.bottom).append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');"; html += "x.domain(d3.extent(data, function(d) { return d.ts}));"; html += "var hrValues = data.map(function(o){return o.hr;}).filter(function(val) {return val !== null});"; html += "var rmssdValues = data.map(function(o){return o.rmssd;}).filter(function(val) {return val !== null});"; html += "y0.domain([d3.min(hrValues) * 0.95, d3.max(data, function(d) {return Math.max(d.hr);}) * 1.01]);"; html += "y1.domain([d3.min(rmssdValues) * 0.95, d3.max(data, function(d) {return Math.max(d.rmssd);}) * 1.01]);"; html += "svg.append('path').style('stroke', '" + Shared.Settings.RetrospectionColorHex + "').attr('d', valueLine1(data)).attr('fill', 'none');"; html += "svg.append('path').style('stroke', '#ff7f0e').attr('d', valueLine2(data)).attr('fill', 'none');"; if (HasAtLeastOneValidHRValue(values)) { html += "svg.append('svg:line').style('stroke', '" + Shared.Settings.RetrospectionColorHex + "').attr('x1', 0).attr('x2', width).attr('y1', y0(" + GetAverageHeartrate(values) + ")).attr('y2', y0(" + GetAverageHeartrate(values) + ")).style('stroke-dasharray', ('12, 9')).style('opacity', 0.4);"; } if (HasAtLeastOneValidRMSSDValue(values)) { html += "svg.append('svg:line').style('stroke', '#ff7f0e').attr('x1', 0).attr('x2', width).attr('y1', y1(" + GetAverageRMSSD(values) + ")).attr('y2', y1(" + GetAverageRMSSD(values) + ")).style('stroke-dasharray', ('12, 9')).style('opacity', 0.4);"; } html += "svg.append('g').attr('class', 'x axis').attr('transform', 'translate(0,' + height + ')').call(xAxis);"; html += "svg.append('g').attr('class', 'y axis').style('fill', '" + Shared.Settings.RetrospectionColorHex + "').call(yAxisLeft);"; html += "svg.append('g').attr('class', 'y axis').attr('transform', 'translate(' + width + ' ,0)').style('fill', '#ff7f0e').call(yAxisRight);"; html += "svg.append('text').attr('x', 0).attr('y', -10).style('text-anchor', 'middle').text('HR');"; html += "svg.append('text').attr('x', width).attr('y', -10).style('text-anchor', 'middle').text('RMSSD');"; html += "</script>"; return(html); }
public override string GetHtml() { var html = string.Empty; //Get Data var hrValues = DatabaseConnector.GetHRValuesForWeek(_date); var rmssdValues = DatabaseConnector.GetRMSSDValuesForWeek(_date); if (hrValues.Count < Settings.NUMBER_OF_BUCKETS || rmssdValues.Count < Settings.NUMBER_OF_BUCKETS) { html += VisHelper.NotEnoughData("It is not possible to give you insights because there is not enough biometric data available."); return(html); } string[] dayNames = CultureInfo.InstalledUICulture.DateTimeFormat.AbbreviatedDayNames; //CSS html += "<style type='text/css'>"; html += ".c3-line { stroke-width: 2px; }"; html += ".c3-grid text, c3.grid line { fill: black; }"; html += "rect.bordered { stroke: #E6E6E6; stroke-width:2px; }"; html += "text.mono { font-size: 7.5pt; fill: #888; }"; html += "text.axis-workweek { fill: #000; }"; html += "text.axis-worktime { fill: #000; }"; html += ".tooltip {background-color: white; box-shadow: 4px 4px 4px #888888; -webkit-box-shadow:2px 3px 4px #888888;padding:2px;position:absolute;top:0px;left:0px;visibility:hidden;border: solid 1px black;border-radius:5px;}"; html += ".dataset-button { padding:0.3125em; background-color:white; border:1px solid " + Shared.Settings.RetrospectionColorHex + "; color:" + Shared.Settings.RetrospectionColorHex + "; text-decoration:none; margin:5px auto; }"; html += ".dataset-button-active { padding:0.3125em; background-color:" + Shared.Settings.RetrospectionColorHex + "; border:1px solid " + Shared.Settings.RetrospectionColorHex + "; color: white; text-decoration:none; margin:5px auto; }"; html += ".dataset-button:hover { background-color:" + Shared.Settings.RetrospectionColorHex + "; border:1px solid " + Shared.Settings.RetrospectionColorHex + "; color:white; cursor: pointer; cursor: hand; }"; html += "</style>"; //HTML html += "<div id='chart'></div>"; html += "<div id='dataset-picker' style='float: right;'></div>"; html += "<p style='text-align: center; font-size: 0.66em;'>Hint: Visualizes your heart rate (HR) and your interbeat interval (RMSSD). (Last time synced with BLE device: " + DatabaseConnector.GetLastTimeSynced().ToString(CultureInfo.InstalledUICulture) + ")</p>"; html += "<div id='dataDiv' class='tooltip'></div>"; //JS html += "<script type='text/javascript'>"; html += "var actualHeight = document.getElementsByClassName('item Wide')[0].offsetHeight;"; html += "var actualWidth = document.getElementsByClassName('item Wide')[0].offsetWidth;"; html += "var margin = { top: 20, right: 0, bottom: 0, left: 40 },"; html += "width = (actualWidth * 0.95) - margin.left - margin.right,"; html += "height = (actualHeight * 0.73) - margin.top - margin.bottom,"; html += "gridSize = Math.floor(width / 24), legendElementWidth = gridSize * 2,"; html += "buckets = " + Settings.NUMBER_OF_BUCKETS + ","; html += GetColorRangeAsJSString(Settings.NUMBER_OF_BUCKETS, Shared.Settings.RetrospectionColorHex); html += "days = ['" + dayNames[(int)DayOfWeek.Monday] + "', '" + dayNames[(int)DayOfWeek.Tuesday] + "', '" + dayNames[(int)DayOfWeek.Wednesday] + "', '" + dayNames[(int)DayOfWeek.Thursday] + "', '" + dayNames[(int)DayOfWeek.Friday] + "', '" + dayNames[(int)DayOfWeek.Saturday] + "', '" + dayNames[(int)DayOfWeek.Sunday] + "'],"; html += "times = ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '22:00', '23:00'];"; html += "var svg = d3.select('#chart').append('svg')"; html += ".attr('width', width + margin.left + margin.right)"; html += ".attr('height', height + margin.top + margin.bottom)"; html += ".append('g')"; html += ".attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');"; html += "var dayLabels = svg.selectAll('.dayLabel')"; html += ".data(days)"; html += ".enter().append('text')"; html += ".text(function(d) { return d; })"; html += ".attr('x', 0)"; html += ".attr('y', function(d, i) { return i * gridSize; })"; html += ".style('text-anchor', 'end')"; html += ".attr('transform', 'translate(-6,' + gridSize / 1.5 + ')')"; html += ".attr('class', function(d, i) { return ((i >= 0 && i <= 4) ? 'dayLabel mono axis axis-workweek' : 'dayLabel mono axis'); });"; html += "var timeLabels = svg.selectAll('.timeLabel')"; html += ".data(times)"; html += ".enter().append('text')"; html += ".text(function(d) { return d; })"; html += ".attr('x', function(d, i) { return i * gridSize; })"; html += ".attr('y', 0)"; html += ".style('text-anchor', 'middle')"; html += ".attr('transform', 'translate(' + gridSize / 2 + ', -6)')"; html += ".attr('class', function(d, i) { return ((i >= 7 && i <= 16) ? 'timeLabel mono axis axis-worktime' : 'timeLabel mono axis'); });"; html += GetDataAsJSString(hrValues, "hrdata"); html += GetDataAsJSString(rmssdValues, "rmssddata"); html += "var heatmapChart = function(data) {"; html += "var colorScale = d3.scale.quantize().domain([d3.min(data, function(d) { return d.value; }), buckets - 1, d3.max(data, function(d) { return d.value; })]).range(colors);"; html += "svg.selectAll('.hour').remove();"; html += "var cards = svg.selectAll('.hour').data(data, function(d) { return d.day + ':' + d.hour; });"; html += "cards.enter().append('rect').attr('x', function(d) { return (d.hour - 1) * gridSize; }).attr('y', function(d) { return (d.day - 1) * gridSize; }).attr('rx', 4).attr('ry', 4).attr('class', 'hour bordered').attr('width', gridSize).attr('height', gridSize).style('fill', colors[0]).attr('data', function(d) { return d.value}).attr('onmouseover', 'showData(evt)').attr('onmouseout', 'hideData(evt)');"; html += "cards.transition().duration(1000).style('fill', function(d) { return colorScale(d.value); });"; html += "cards.exit().remove();"; html += "svg.selectAll('.legend').remove();"; html += "var legend = svg.selectAll('.legend').data(colorScale.range(), function(d) { return d; });"; html += "legend.enter().append('g').attr('class', 'legend');"; html += "legend.append('rect').attr('x', function(d, i) { return legendElementWidth * i; }).attr('y', height-15).attr('width', legendElementWidth).attr('height', gridSize / 2).style('fill', function(d, i) { return colors[i]; });"; html += "legend.append('text').attr('class', 'mono').text(function(d) { var r = colorScale.invertExtent(d); return '≥ ' + d3.format('.2f')(r[0]); }).attr('x', function(d, i) { return legendElementWidth * i; }).attr('y', height - (0.5 * gridSize));"; html += "legend.exit().remove();"; html += "};"; html += "heatmapChart(hrdata);"; html += "d3.select('#dataset-picker').append('input').attr('type', 'button').attr('value', 'HR').attr('class', 'dataset-button-active').attr('id', 'hrbutton').on('click', function() {document.getElementById('rmssdbutton');document.getElementById('rmssdbutton').style.backgroundColor='White';document.getElementById('rmssdbutton').style.color='black';this.style.backgroundColor = '" + Shared.Settings.RetrospectionColorHex + "';this.style.color='white';heatmapChart(hrdata);});"; html += "d3.select('#dataset-picker').append('input').attr('type', 'button').attr('value', 'RMSSD').attr('class', 'dataset-button').attr('id', 'rmssdbutton').on('click', function() {document.getElementById('hrbutton');document.getElementById('hrbutton').style.backgroundColor='White';document.getElementById('hrbutton').style.color='black';this.style.backgroundColor = '" + Shared.Settings.RetrospectionColorHex + "';this.style.color='white';heatmapChart(rmssddata);});"; html += "function showData(evt) { var target = evt.target; target.setAttribute('opacity', '.8');"; html += "var x = evt.clientX;"; html += "var y = evt.clientY;"; html += "var offsetX = window.pageXOffset;"; html += "var offsetY = window.pageYOffset;"; html += "dataDiv.style.left = 10 + x + offsetX + 'px';"; html += "dataDiv.style.top = 20 + y + offsetY + 'px';"; html += "var data = target.getAttribute('data');"; html += "var html = data;"; html += "dataDiv.innerHTML = html;"; html += "dataDiv.style.visibility = 'visible';"; html += "}"; html += "function hideData(evt) {"; html += "dataDiv.style.visibility = 'hidden';"; html += "var target = evt.target;"; html += "target.removeAttribute('opacity');"; html += "}"; html += "</script>"; return(html); }
public override string GetHtml() { var html = string.Empty; ///////////////////// // fetch data sets ///////////////////// var chartQueryResultsLocal = Queries.GetUserInputTimelineData_v2(_date); // if no user input data available, try to get it from the old data (V1 user input tracker) // TODO: remove at some point (when no one is using the old user-input tracker anymore) //if (chartQueryResultsLocal.Sum(i => i.Value) == 0) //{ // chartQueryResultsLocal = Queries.GetUserInputTimelineData_v1(_date); //} // 3 is the minimum number of input-data-items - else, it makes no sense to show a visualization if (chartQueryResultsLocal.Count < 3) { html += VisHelper.NotEnoughData(Dict.NotEnoughData); return(html); } ///////////////////// // CSS ///////////////////// html += "<style type='text/css'>"; html += ".c3-line { stroke-width: 2px; }"; html += ".c3-grid text, c3.grid line { fill: gray; }"; html += "</style>"; ///////////////////// // HTML ///////////////////// html += "<div id='" + VisHelper.CreateChartHtmlTitle(Title) + "' style='height:75%;' align='center'></div>"; html += "<p style='text-align: center; font-size: 0.66em;'>Hint: Visualizes your active times, based on your keyboard and mouse input.</p>"; ///////////////////// // JS ///////////////////// var ticks = CalculateLineChartAxisTicks(_date); var timeAxis = chartQueryResultsLocal.Aggregate("", (current, a) => current + (DateTimeHelper.JavascriptTimestampFromDateTime(a.Key) + ", ")).Trim().TrimEnd(','); var userInputFormattedData = chartQueryResultsLocal.Aggregate("", (current, p) => current + (p.Value + ", ")).Trim().TrimEnd(','); var maxUserInput = chartQueryResultsLocal.Max(i => i.Value); var avgUserInput = chartQueryResultsLocal.Average(i => i.Value); const string colors = "'User_Input_Level' : '" + Shared.Settings.RetrospectionColorHex + "'"; var data = "x: 'timeAxis', columns: [['timeAxis', " + timeAxis + "], ['User_Input_Level', " + userInputFormattedData + " ] ], type: 'area', colors: { " + colors + " }, axis: { 'PerceivedProductivity': 'y' }"; var grid = "y: { lines: [ { value: 0, text: 'not active' }, { value: " + avgUserInput + ", text: 'average activity today' }, { value: " + maxUserInput + ", text: 'max activity today' } ] } "; var axis = "x: { localtime: true, type: 'timeseries', tick: { values: [ " + ticks + "], format: function(x) { return formatDate(x.getHours()); }} }, y: { show: false, min: 0 }"; var parameters = " bindto: '#" + VisHelper.CreateChartHtmlTitle(Title) + "', data: { " + data + " }, padding: { left: 0, right: 0, bottom: -10, top: 0}, legend: { show: false }, axis: { " + axis + " }, grid: { " + grid + " }, tooltip: { show: false }, point: { show: false }"; // padding: { left: 0, right: 0 }, html += "<script type='text/javascript'>"; html += "var formatDate = function(hours) { var suffix = 'AM'; if (hours >= 12) { suffix = 'PM'; hours = hours - 12; } if (hours == 0) { hours = 12; } if (hours < 10) return '0' + hours + ' ' + suffix; else return hours + ' ' + suffix; };"; html += "var " + VisHelper.CreateChartHtmlTitle(Title) + " = c3.generate({ " + parameters + " });"; // return x.getHours() + ':' + x.getMinutes(); html += "</script>"; return(html); }