{"id":18521812,"url":"https://github.com/simphotonics/time_tracker","last_synced_at":"2025-05-14T18:09:23.931Z","repository":{"id":71883618,"uuid":"601311046","full_name":"simphotonics/time_tracker","owner":"simphotonics","description":"A serializable Dart object that records time-status changes.","archived":false,"fork":false,"pushed_at":"2024-05-23T20:24:47.000Z","size":74,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-17T05:25:27.359Z","etag":null,"topics":["async","dart","time","timepoint"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/time_tracker","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simphotonics.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-13T19:58:49.000Z","updated_at":"2024-05-23T20:24:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"eb9d754d-2b2c-4262-8a37-bf6dfabeed23","html_url":"https://github.com/simphotonics/time_tracker","commit_stats":{"total_commits":25,"total_committers":1,"mean_commits":25.0,"dds":0.0,"last_synced_commit":"a8dd3f34019db9a28487f3608d0fca389372cab2"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Ftime_tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Ftime_tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Ftime_tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Ftime_tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simphotonics","download_url":"https://codeload.github.com/simphotonics/time_tracker/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198510,"owners_count":22030966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","dart","time","timepoint"],"created_at":"2024-11-06T17:27:43.459Z","updated_at":"2025-05-14T18:09:18.885Z","avatar_url":"https://github.com/simphotonics.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Time Tracker\n[![Dart](https://github.com/simphotonics/time_tracker/actions/workflows/dart.yml/badge.svg)](https://github.com/simphotonics/time_tracker/actions/workflows/dart.yml)\n\n## Introduction\n\nA commonly required task consists in recording the time a process *starts*, is *paused/resumed*,\nand the time it\nis *completed*. An object of type [`TimeTracker`][TimeTracker] is designed to perform this job.\nIt is similar to a [`StopWatch`][StopWatch],\nhowever instead of elapsed ticks it records a [`DateTime`][DateTime] point\nwhenever its status changes.\n\nThe image below shows the available states (blue font) defined by\nthe enum [`TimeStatus`][TimeStatus] and available transitions (orange arrows)\ndefined by the class [`TimeTracker`][TimeTracker].\n\n![TimeStatus](https://github.com/simphotonics/time_tracker/raw/main/images/time_status.svg?sanitize=true)\n\nStatus changing methods are printed with green font. Calling a status changing\nmethod where there is no transition defined has no effect.\nFor example: calling the method `end()` when the object has status\n`TimeStatus.ready` has no effect.\n\nIn addition to methods for recording time points,\nthe mixin [`TimeTracker`][TimeTracker] provides helper methods\nfor json-serialization. It is recommended that classes *with*\n[`TimeTracker`][TimeTracker] override\nthe equality operator such that a deserialized object will compare equal\nto the original object.\n\n## Usage\n\nTo use this library include [`time_tracker`][time_tracker]\nas a dependency in your pubspec.yaml file.\n\nThe example below shows how to construct an object of type `TennisMatch` with\nthe mixin `TimeTracker`. The object records its own time\npoints. Note: The getter `hashCode` and the equality operator are overriden\nso that decoded objects are equal to the original object.\n\n```Dart\nimport 'package:exception_templates/exception_templates.dart';\nimport 'package:time_tracker/time_tracker.dart';\n\n/// Demonstrates how to use TimeTracker.\nclass TennisMatch with TimeTracker {\n  final _players = \u003cString\u003e[];\n\n  TennisMatch(List\u003cString\u003e players) {\n    _players.addAll(players);\n  }\n\n  /// Constructs an object from a json map.\n  TennisMatch.fromJson(Map\u003cString, dynamic\u003e json) {\n    if (json case {'players': List players}) {\n      _players.addAll(players.cast\u003cString\u003e());\n\n      // Uses the entries of json to initialize the time tracker state.\n      initTrackerfromJson(json);\n    } else {\n      throw ErrorOf\u003cTennisMatch\u003e(\n        message: 'Error validating list of players.',\n        invalidState: ' Found map: $json',\n      );\n    }\n  }\n\n  @override\n  Map\u003cString, dynamic\u003e toJson() {\n\n    // Adds the map entries related to the time tracker.\n    final json = trackerToJson();\n    json['players'] = List\u003cString\u003e.of(_players);\n    return json;\n  }\n\n  @override\n  int get hashCode =\u003e Object.hash(trackerHashCode, _players);\n\n  /// Returns `true` if the two instances have the same time status,\n  /// time points, and player list.\n  @override\n  bool operator ==(Object other) {\n    return other is TennisMatch \u0026\u0026\n        _players.equal(other._players) \u0026\u0026\n        trackerEqual(other);\n  }\n\n  @override\n  String toString() {\n    return 'TennisMatch: players: $_players | status: ${status.name} '\n        '| duration: $duration';\n  }\n}\n```\n\nThe program below demonstrates how to use an object of type `TennisMatch` to\nstart, pause, resume, and end the match. It also shows how to serialize and\ndeserialize the object using ['dart:convert'][dart:convert].\n\n```Dart\nvoid main() async {\n  /// Create object (start time is recorded)\n  final match = TennisMatch(['Tim', 'Andy'])..start();\n\n  print('----- Create an object of type TennisMatch -----');\n  print('Status: ${match.status.name} at: ${match.startTime}');\n\n  await Future.delayed(const Duration(milliseconds: 3), () {\n    // Pause object\n    match.pause();\n    print('Status: ${match.status.name} at: ${match.lastTimePoint}');\n  });\n\n  await Future.delayed(const Duration(milliseconds: 1), () {\n    // Resume object\n    match.resume();\n    print('Status: ${match.status.name} at: ${match.lastTimePoint}');\n  });\n\n  await Future.delayed(const Duration(milliseconds: 2), () {\n    // Mark object as ended.\n    match.end();\n    print('Status: ${match.status.name} at: ${match.lastTimePoint}');\n  });\n\n  print('');\n  print('---------- Json Encoding -------------');\n  final jsonString = jsonEncode(match);\n  print('Serialized object:');\n  print(jsonString);\n\n  var decodedMatch = TennisMatch.fromJson(jsonDecode(jsonString));\n  print('');\n  print('Deserialized object:');\n  print(decodedMatch);\n\n  print('');\n  print('match == decodedMatch: ${match == decodedMatch}');\n}\n```\n\n\u003cdetails\u003e \u003csummary\u003e Click to show the console output. \u003c/summary\u003e\n\n```Console\n$ dart example/bin/time_tracker_example.dart\n----- Create an object of type TennisMatch -----\nStatus: started at: 2024-05-23 21:23:27.831544\nStatus: paused at: 2024-05-23 21:23:30.841633\nStatus: resumed at: 2024-05-23 21:23:31.845723\nStatus: ended at: 2024-05-23 21:23:33.847798\n\n---------- Json Encoding -------------\nSerialized object:\n{\"_status\":{\"timeStatus\":\"ended\"},\"_timePoints\":[1716495807831544,1716495810841633,1716495811845723,1716495813847798],\"players\":[\"Tim\",\"Andy\"]}\n\nDeserialized object:\nTennisMatch: players: [Tim, Andy] | status: ended | duration: 0:00:05.012164\n\nmatch == decodedMatch: true\n```\n\u003c/details\u003e\n\n## Example\n\nThe source code of the program shown above can be found in the folder [example].\n\n## Features and bugs\n\nPlease file feature requests and bugs at the [issue tracker].\n\n[issue tracker]: https://github.com/simphotonics/time_tracker/issues\n\n[dart:convert]: https://api.dart.dev/stable/dart-convert/dart-convert-library.html\n\n[DateTime]: https://api.dart.dev/stable/dart-core/DateTime-class.html\n\n[example]: example\n\n[time_tracker]: https://pub.dev/packages/time_tracker\n\n[TimeStatus]: https://pub.dev/documentation/time_tracker/latest/time_tracker/TimeStatus.html\n\n[TimeTracker]: https://pub.dev/documentation/time_tracker/latest/time_tracker/TimeTracker-mixin.html\n\n[StopWatch]: https://api.dart.dev/stable/dart-core/Stopwatch-class.html","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Ftime_tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimphotonics%2Ftime_tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Ftime_tracker/lists"}