{"id":22640729,"url":"https://github.com/emptyshop/sumatiempos","last_synced_at":"2025-03-29T05:25:45.171Z","repository":{"id":156622503,"uuid":"220558489","full_name":"EmptyShop/SumaTiempos","owner":"EmptyShop","description":"App Android para sumar tiempos.","archived":false,"fork":false,"pushed_at":"2022-06-22T22:15:25.000Z","size":235,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-03T15:55:01.910Z","etag":null,"topics":["android","kotlin"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EmptyShop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2019-11-08T22:36:39.000Z","updated_at":"2022-06-22T22:15:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"96739f9a-10ca-479e-b097-a3b1a76df924","html_url":"https://github.com/EmptyShop/SumaTiempos","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmptyShop%2FSumaTiempos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmptyShop%2FSumaTiempos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmptyShop%2FSumaTiempos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmptyShop%2FSumaTiempos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EmptyShop","download_url":"https://codeload.github.com/EmptyShop/SumaTiempos/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246143325,"owners_count":20730242,"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":["android","kotlin"],"created_at":"2024-12-09T04:13:35.657Z","updated_at":"2025-03-29T05:25:45.142Z","avatar_url":"https://github.com/EmptyShop.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SumaTiempos\nApp Android para sumar tiempos.\n## De qué se trata esta app\nHice mi primera app operativa para practicar lo poco que sabía de Android, hace algunos años. Me gusta correr y como no me gusta descargar apps y llenar el teléfono de cosas que nunca voy a usar preferí hacer mi propia aplicación para llevar el registro de mis tiempos cuando voy a correr.\n\nLa operación es así: tengo 2 widgets de texto para capturar minutos y segundos, un botón para sumar los tiempos capturados, etiquetas de texto para el histórico y para el total acumulado.\n\n## Cómo lo hice\nProgramé mi app para Android, usando Kotlin. Específicamente, quedó terminada con las siguientes versiones:\n  * SDK target 29\n  * SDK mínimo 15\n  * Kotlin 1.3.50\n  * Gradle 3.5.2\n\nConstruí una clase para que se haga cargo de los cálculos y formateo:\n```sh\nclass Tiempo (_horas : Int = 0, _minutos : Int = 0, _segundos : Int = 0, _milisegundos : Int = 0){\n    /* Constructor : Acepta 4 parámetros opcionales:\n    _horas : Int, _minutos : Int, _segundos : Int, _milisegundos : Int */\n    var horas : Int = _horas\n    var minutos : Int = _minutos\n    set (value){\n        field = if (value \u003c 60) value else 0\n    }\n    var segundos : Int = _segundos\n    set(value){\n        field = if (value \u003c 60) value else 0\n    }\n    var milisegundos : Int = _milisegundos\n    set(value){\n        field = if (value \u003c 1000) value else 0\n    }\n\n    /* suma() : Suma 2 objetos de tipo Tiempo y devuelve el resultado.\n    Parámetros:\n    sumando : Tiempo\n     */\n    fun suma(sumando : Tiempo) : Tiempo {\n        val ms = this.milisegundos + sumando.milisegundos\n        this.milisegundos = ms % 1000\n        this.segundos += ms.div(1000)\n\n        val s = this.segundos + sumando.segundos\n        this.segundos = s % 60\n        this.minutos += s.div(60)\n\n        val m = this.minutos + sumando.minutos\n        this.minutos = m % 60\n        this.horas += m.div(60)\n\n        val h = this.horas + sumando.horas\n        this.horas = h\n\n        return this\n    }\n\n    /* toString() : Despliega el valor del objeto en formato h mm ss .ms */\n    override fun toString() : String{\n        val s = StringBuilder()\n        s.append(this.horas.toString())\n            .append(\"h \")\n            .append(this.minutos.toString().padStart(2, '0'))\n            .append(\"m \")\n            .append(this.segundos.toString().padStart(2,'0'))\n            .append(\".\")\n            .append(this.milisegundos.toString().padStart(3,'0'))\n            .append(\"s\")\n\n        return s.toString()\n    }\n}\n```\nEn la clase MainActivity sólo haga validaciones de captura y actualización de resultados. Lo que puedo destacar de esta parte es la validación que resultó en código muy compacto pero notablemente eficiente:\n```sh\n/* Agrega un listener para validar campos de texto. */\nfun EditText.afterTextChanged(afterTextChanged : (String) -\u003e Unit){\n    this.addTextChangedListener(object : TextWatcher {\n        override fun afterTextChanged(s: Editable?) {\n            afterTextChanged.invoke(s.toString())\n        }\n\n        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }\n        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }\n    })\n}\n\n/* Validador para campos de texto. */\nfun EditText.validate(message : String, validator : (String) -\u003e Boolean){\n    this.afterTextChanged {\n        this.error = if (validator(it)) null else message\n    }\n    this.error = if (validator(this.text.toString())) null else message\n}\n```\n## Finalmente\nResultó muy útil y es una app muy ligera, a diferencia de las apps comerciales que tienen docenas de característica que no necesito. Y eso es todo con respecto a mi app Suma Tiempos.\n\n*EmptyShop*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femptyshop%2Fsumatiempos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femptyshop%2Fsumatiempos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femptyshop%2Fsumatiempos/lists"}