diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..7707294 --- /dev/null +++ b/404.html @@ -0,0 +1,2142 @@ + + + + + + + + + + + + + + + + + + + 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/alinhamento/canais/index.html b/alinhamento/canais/index.html new file mode 100644 index 0000000..c916fa7 --- /dev/null +++ b/alinhamento/canais/index.html @@ -0,0 +1,2298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Canais de comunicação - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Canais de comunicação

+

Para manter o time alinhado foram escolhidos alguns canais de comunicação para reuniões, discussões rápidas, organização de atividades e gerenciamento do projeto.

+

Plataformas escolhidas

+
    +
  • +

    Telegram: usado para comunicação rápida da equipe e passagem de informações rotineiras.

    +
  • +
  • +

    Microsoft Teams: usado para reuniões com cliente, bem como para realizar e gravar treinamentos realizados com os MDS (DOJO).

    +
  • +
  • +

    Zenhub: usado para criar e compartilhar o quadro kanban da equipe.

    +
  • +
  • +

    Discord: usado para pareamentos e reuniões do time que não precisam ser gravadas.

    +
  • +
  • +

    Github: usado para repositórios de documentação e issues assim como repositórios de código fonte.

    +
  • +
  • +

    Google Drive: usado para salvar e compartilhar arquivos.

    +
  • +
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento27/03/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/alinhamento/disponibilidade/index.html b/alinhamento/disponibilidade/index.html new file mode 100644 index 0000000..88aa345 --- /dev/null +++ b/alinhamento/disponibilidade/index.html @@ -0,0 +1,2311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Quadro de disponibilidade - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Quadro de disponibilidade

+

Para facilitar o agendamento de reuniões do time foi criada uma planilha de disponibilidade. Cada um preencheu a planilha com horários em que os integrantes estavam livres e os horários disponíveis com agendamento prévio, porém com a quantidade de pessoas na equipe foi difícil encontrar horários em que todos estivessem livres. Dessa forma, foi definido um quórum mínimo de reunião de 8 pessoas (garantindo um mínimo de metade dos MDS presentes).

+ + +

Horários de reuniões

+ + + + + + + + + + + + + + + + + + + + +
ReuniãoHorárioModelo
Reunião com clienteToda segunda às 20hRemoto
DojoEsporadicamente conforme agendamentoRemoto/Presencial
+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento27/03/24Sara Campos
Correções28/03/24Sara Campos
Atualização03/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/alinhamento/dojos/index.html b/alinhamento/dojos/index.html new file mode 100644 index 0000000..3def114 --- /dev/null +++ b/alinhamento/dojos/index.html @@ -0,0 +1,2346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planejamento de dojos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Dojo

+

Os dojos são treinamentos realizados pelos EPS para contribuir com a evolução do conhecimento técnico dos MDS ao longo da disciplina. Conforme as tecnologias usadas neste projeto e a demanda de treinamento, os dojos devem ser agendados. Abaixo segue a lista de treinamentos já realizados pela equipe. Nas issues do nosso Github podem ser encontrados mais detalhes sobre cada um dos dojos.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TópicoDataHorárioResponsávelModelo
Git27/03/2421hVictor YukioRemoto
Scrum + Kanban04/04/2413hSara CamposPresencial + Remoto
HTML + CSS + Material UI + Princípios de ReactJS06/04/2415hVictor YukioRemoto
Frontend Vite.js11/07/2420hSara Campos, Ingrid Carvalho e Victor YukioRemoto
Backend Node Express16/07/2420hVictor YukioRemoto
Figma20/07/249hSara CamposRemoto
Testes unitários com Vitest e Jest14/08/2420h30Sara Campos e Victor YukioRemoto
+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento27/03/24Sara Campos
Atualização05/04/24Sara Campos
Atualização06/04/24Sara Campos
Atualização18/07/24Sara Campos
Atualização20/07/24Sara Campos
Atualização16/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/alinhamento/heatmap/index.html b/alinhamento/heatmap/index.html new file mode 100644 index 0000000..7250141 --- /dev/null +++ b/alinhamento/heatmap/index.html @@ -0,0 +1,2267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Quadro de conhecimento - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Quadro de conhecimento

+

Para entender de onde cada integrante está partindo em termos de conhecimento sobre as tecnologias usadas e monitorar a evolução de cada um ao longo da disciplina foi criado um quadro de conhecimento. A equipe preencheu o quadro conforme uma autoavaliação do seu nível de conhecimento técnico. Esse quadro ajuda a avaliar demanda de dojos para os MDS, assim como ajuda a formar bons pareamentos conforme as habilidades de cada pessoa do time.

+ + +

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento27/03/24Sara Campos
Atualização03/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/assets/Arquitetura_SENTINELA.png b/assets/Arquitetura_SENTINELA.png new file mode 100644 index 0000000..f99f754 Binary files /dev/null and b/assets/Arquitetura_SENTINELA.png differ diff --git a/assets/Conceitual_Finance.png b/assets/Conceitual_Finance.png new file mode 100644 index 0000000..3563d64 Binary files /dev/null and b/assets/Conceitual_Finance.png differ diff --git a/assets/Conceitual_benefits.png b/assets/Conceitual_benefits.png new file mode 100644 index 0000000..e32265e Binary files /dev/null and b/assets/Conceitual_benefits.png differ diff --git a/assets/Conceitual_users.png b/assets/Conceitual_users.png new file mode 100644 index 0000000..5731724 Binary files /dev/null and b/assets/Conceitual_users.png differ diff --git a/assets/R1_EVM.png b/assets/R1_EVM.png new file mode 100644 index 0000000..52efab5 Binary files /dev/null and b/assets/R1_EVM.png differ diff --git a/assets/RMVP_EVM.png b/assets/RMVP_EVM.png new file mode 100644 index 0000000..4e2430b Binary files /dev/null and b/assets/RMVP_EVM.png differ diff --git a/assets/RN_EVM.png b/assets/RN_EVM.png new file mode 100644 index 0000000..f7ca4b9 Binary files /dev/null and b/assets/RN_EVM.png differ diff --git a/assets/TOTAL_EVM.png b/assets/TOTAL_EVM.png new file mode 100644 index 0000000..fcc49d9 Binary files /dev/null and b/assets/TOTAL_EVM.png differ diff --git a/assets/alvaro.jpeg b/assets/alvaro.jpeg new file mode 100644 index 0000000..3ab63c4 Binary files /dev/null and b/assets/alvaro.jpeg differ diff --git a/assets/anna.jpeg b/assets/anna.jpeg new file mode 100644 index 0000000..8aaf64e Binary files /dev/null and b/assets/anna.jpeg differ diff --git a/assets/arq.png b/assets/arq.png new file mode 100644 index 0000000..d037be8 Binary files /dev/null and b/assets/arq.png differ diff --git a/assets/backlog.png b/assets/backlog.png new file mode 100644 index 0000000..75fafe0 Binary files /dev/null and b/assets/backlog.png differ diff --git a/assets/bs1.png b/assets/bs1.png new file mode 100644 index 0000000..4f3830c Binary files /dev/null and b/assets/bs1.png differ diff --git a/assets/bs2.png b/assets/bs2.png new file mode 100644 index 0000000..aef3de1 Binary files /dev/null and b/assets/bs2.png differ diff --git a/assets/canvasmvp.png b/assets/canvasmvp.png new file mode 100644 index 0000000..9fef117 Binary files /dev/null and b/assets/canvasmvp.png differ diff --git a/assets/diogo.jpeg b/assets/diogo.jpeg new file mode 100644 index 0000000..11f7f2f Binary files /dev/null and b/assets/diogo.jpeg differ diff --git a/assets/dmesquita.jpeg b/assets/dmesquita.jpeg new file mode 100644 index 0000000..123cf7d Binary files /dev/null and b/assets/dmesquita.jpeg differ diff --git a/assets/dnobre.jpeg b/assets/dnobre.jpeg new file mode 100644 index 0000000..81ccd17 Binary files /dev/null and b/assets/dnobre.jpeg differ diff --git a/assets/eap.png b/assets/eap.png new file mode 100644 index 0000000..5fd0c03 Binary files /dev/null and b/assets/eap.png differ diff --git a/assets/enfn.png b/assets/enfn.png new file mode 100644 index 0000000..c49df7c Binary files /dev/null and b/assets/enfn.png differ diff --git a/assets/guilherme.jpeg b/assets/guilherme.jpeg new file mode 100644 index 0000000..cb6728c Binary files /dev/null and b/assets/guilherme.jpeg differ diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/ingrid.jpeg b/assets/ingrid.jpeg new file mode 100644 index 0000000..252b726 Binary files /dev/null and b/assets/ingrid.jpeg differ diff --git a/assets/j1v.png b/assets/j1v.png new file mode 100644 index 0000000..f2c617e Binary files /dev/null and b/assets/j1v.png differ diff --git a/assets/j2v.png b/assets/j2v.png new file mode 100644 index 0000000..6231c9b Binary files /dev/null and b/assets/j2v.png differ diff --git a/assets/j3v.png b/assets/j3v.png new file mode 100644 index 0000000..0db532d Binary files /dev/null and b/assets/j3v.png differ diff --git a/assets/j4v.png b/assets/j4v.png new file mode 100644 index 0000000..cdb89cc Binary files /dev/null and b/assets/j4v.png differ diff --git a/assets/j5v.png b/assets/j5v.png new file mode 100644 index 0000000..d49998a Binary files /dev/null and b/assets/j5v.png differ diff --git a/assets/j6v.png b/assets/j6v.png new file mode 100644 index 0000000..65fc3a7 Binary files /dev/null and b/assets/j6v.png differ diff --git a/assets/javascripts/bundle.56dfad97.min.js b/assets/javascripts/bundle.56dfad97.min.js new file mode 100644 index 0000000..1df62cd --- /dev/null +++ b/assets/javascripts/bundle.56dfad97.min.js @@ -0,0 +1,16 @@ +"use strict";(()=>{var Fi=Object.create;var gr=Object.defineProperty;var Wi=Object.getOwnPropertyDescriptor;var Ui=Object.getOwnPropertyNames,Vt=Object.getOwnPropertySymbols,Di=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,io=Object.prototype.propertyIsEnumerable;var no=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,$=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&no(e,r,t[r]);if(Vt)for(var r of Vt(t))io.call(t,r)&&no(e,r,t[r]);return e};var ao=(e,t)=>{var r={};for(var o in e)yr.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Vt)for(var o of Vt(e))t.indexOf(o)<0&&io.call(e,o)&&(r[o]=e[o]);return r};var xr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Vi=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ui(t))!yr.call(e,n)&&n!==r&&gr(e,n,{get:()=>t[n],enumerable:!(o=Wi(t,n))||o.enumerable});return e};var Lt=(e,t,r)=>(r=e!=null?Fi(Di(e)):{},Vi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var so=(e,t,r)=>new Promise((o,n)=>{var i=p=>{try{s(r.next(p))}catch(c){n(c)}},a=p=>{try{s(r.throw(p))}catch(c){n(c)}},s=p=>p.done?o(p.value):Promise.resolve(p.value).then(i,a);s((r=r.apply(e,t)).next())});var po=xr((Er,co)=>{(function(e,t){typeof Er=="object"&&typeof co!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Er,function(){"use strict";function e(r){var o=!0,n=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(k){return!!(k&&k!==document&&k.nodeName!=="HTML"&&k.nodeName!=="BODY"&&"classList"in k&&"contains"in k.classList)}function p(k){var ft=k.type,qe=k.tagName;return!!(qe==="INPUT"&&a[ft]&&!k.readOnly||qe==="TEXTAREA"&&!k.readOnly||k.isContentEditable)}function c(k){k.classList.contains("focus-visible")||(k.classList.add("focus-visible"),k.setAttribute("data-focus-visible-added",""))}function l(k){k.hasAttribute("data-focus-visible-added")&&(k.classList.remove("focus-visible"),k.removeAttribute("data-focus-visible-added"))}function f(k){k.metaKey||k.altKey||k.ctrlKey||(s(r.activeElement)&&c(r.activeElement),o=!0)}function u(k){o=!1}function d(k){s(k.target)&&(o||p(k.target))&&c(k.target)}function y(k){s(k.target)&&(k.target.classList.contains("focus-visible")||k.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(k.target))}function M(k){document.visibilityState==="hidden"&&(n&&(o=!0),X())}function X(){document.addEventListener("mousemove",J),document.addEventListener("mousedown",J),document.addEventListener("mouseup",J),document.addEventListener("pointermove",J),document.addEventListener("pointerdown",J),document.addEventListener("pointerup",J),document.addEventListener("touchmove",J),document.addEventListener("touchstart",J),document.addEventListener("touchend",J)}function te(){document.removeEventListener("mousemove",J),document.removeEventListener("mousedown",J),document.removeEventListener("mouseup",J),document.removeEventListener("pointermove",J),document.removeEventListener("pointerdown",J),document.removeEventListener("pointerup",J),document.removeEventListener("touchmove",J),document.removeEventListener("touchstart",J),document.removeEventListener("touchend",J)}function J(k){k.target.nodeName&&k.target.nodeName.toLowerCase()==="html"||(o=!1,te())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",M,!0),X(),r.addEventListener("focus",d,!0),r.addEventListener("blur",y,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var qr=xr((ly,Sn)=>{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var ka=/["'&<>]/;Sn.exports=Ha;function Ha(e){var t=""+e,r=ka.exec(t);if(!r)return t;var o,n="",i=0,a=0;for(i=r.index;i{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof It=="object"&&typeof Yr=="object"?Yr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof It=="object"?It.ClipboardJS=r():t.ClipboardJS=r()})(It,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return ji}});var a=i(279),s=i.n(a),p=i(370),c=i.n(p),l=i(817),f=i.n(l);function u(V){try{return document.execCommand(V)}catch(A){return!1}}var d=function(A){var L=f()(A);return u("cut"),L},y=d;function M(V){var A=document.documentElement.getAttribute("dir")==="rtl",L=document.createElement("textarea");L.style.fontSize="12pt",L.style.border="0",L.style.padding="0",L.style.margin="0",L.style.position="absolute",L.style[A?"right":"left"]="-9999px";var F=window.pageYOffset||document.documentElement.scrollTop;return L.style.top="".concat(F,"px"),L.setAttribute("readonly",""),L.value=V,L}var X=function(A,L){var F=M(A);L.container.appendChild(F);var D=f()(F);return u("copy"),F.remove(),D},te=function(A){var L=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},F="";return typeof A=="string"?F=X(A,L):A instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(A==null?void 0:A.type)?F=X(A.value,L):(F=f()(A),u("copy")),F},J=te;function k(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?k=function(L){return typeof L}:k=function(L){return L&&typeof Symbol=="function"&&L.constructor===Symbol&&L!==Symbol.prototype?"symbol":typeof L},k(V)}var ft=function(){var A=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},L=A.action,F=L===void 0?"copy":L,D=A.container,Y=A.target,$e=A.text;if(F!=="copy"&&F!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(Y!==void 0)if(Y&&k(Y)==="object"&&Y.nodeType===1){if(F==="copy"&&Y.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(F==="cut"&&(Y.hasAttribute("readonly")||Y.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if($e)return J($e,{container:D});if(Y)return F==="cut"?y(Y):J(Y,{container:D})},qe=ft;function Fe(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Fe=function(L){return typeof L}:Fe=function(L){return L&&typeof Symbol=="function"&&L.constructor===Symbol&&L!==Symbol.prototype?"symbol":typeof L},Fe(V)}function Ai(V,A){if(!(V instanceof A))throw new TypeError("Cannot call a class as a function")}function oo(V,A){for(var L=0;L0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof D.action=="function"?D.action:this.defaultAction,this.target=typeof D.target=="function"?D.target:this.defaultTarget,this.text=typeof D.text=="function"?D.text:this.defaultText,this.container=Fe(D.container)==="object"?D.container:document.body}},{key:"listenClick",value:function(D){var Y=this;this.listener=c()(D,"click",function($e){return Y.onClick($e)})}},{key:"onClick",value:function(D){var Y=D.delegateTarget||D.currentTarget,$e=this.action(Y)||"copy",Dt=qe({action:$e,container:this.container,target:this.target(Y),text:this.text(Y)});this.emit(Dt?"success":"error",{action:$e,text:Dt,trigger:Y,clearSelection:function(){Y&&Y.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(D){return vr("action",D)}},{key:"defaultTarget",value:function(D){var Y=vr("target",D);if(Y)return document.querySelector(Y)}},{key:"defaultText",value:function(D){return vr("text",D)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(D){var Y=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return J(D,Y)}},{key:"cut",value:function(D){return y(D)}},{key:"isSupported",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],Y=typeof D=="string"?[D]:D,$e=!!document.queryCommandSupported;return Y.forEach(function(Dt){$e=$e&&!!document.queryCommandSupported(Dt)}),$e}}]),L}(s()),ji=Ii},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,p){for(;s&&s.nodeType!==n;){if(typeof s.matches=="function"&&s.matches(p))return s;s=s.parentNode}}o.exports=a},438:function(o,n,i){var a=i(828);function s(l,f,u,d,y){var M=c.apply(this,arguments);return l.addEventListener(u,M,y),{destroy:function(){l.removeEventListener(u,M,y)}}}function p(l,f,u,d,y){return typeof l.addEventListener=="function"?s.apply(null,arguments):typeof u=="function"?s.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(M){return s(M,f,u,d,y)}))}function c(l,f,u,d){return function(y){y.delegateTarget=a(y.target,f),y.delegateTarget&&d.call(l,y)}}o.exports=p},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(o,n,i){var a=i(879),s=i(438);function p(u,d,y){if(!u&&!d&&!y)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(y))throw new TypeError("Third argument must be a Function");if(a.node(u))return c(u,d,y);if(a.nodeList(u))return l(u,d,y);if(a.string(u))return f(u,d,y);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(u,d,y){return u.addEventListener(d,y),{destroy:function(){u.removeEventListener(d,y)}}}function l(u,d,y){return Array.prototype.forEach.call(u,function(M){M.addEventListener(d,y)}),{destroy:function(){Array.prototype.forEach.call(u,function(M){M.removeEventListener(d,y)})}}}function f(u,d,y){return s(document.body,u,d,y)}o.exports=p},817:function(o){function n(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var p=window.getSelection(),c=document.createRange();c.selectNodeContents(i),p.removeAllRanges(),p.addRange(c),a=p.toString()}return a}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,a,s){var p=this.e||(this.e={});return(p[i]||(p[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var p=this;function c(){p.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),p=0,c=s.length;for(p;p0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function N(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],a;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(s){a={error:s}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(a)throw a.error}}return i}function q(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||p(d,M)})},y&&(n[d]=y(n[d])))}function p(d,y){try{c(o[d](y))}catch(M){u(i[0][3],M)}}function c(d){d.value instanceof nt?Promise.resolve(d.value.v).then(l,f):u(i[0][2],d)}function l(d){p("next",d)}function f(d){p("throw",d)}function u(d,y){d(y),i.shift(),i.length&&p(i[0][0],i[0][1])}}function fo(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof he=="function"?he(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(a){return new Promise(function(s,p){a=e[i](a),n(s,p,a.done,a.value)})}}function n(i,a,s,p){Promise.resolve(p).then(function(c){i({value:c,done:s})},a)}}function H(e){return typeof e=="function"}function ut(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var zt=ut(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Qe(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var We=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=he(a),p=s.next();!p.done;p=s.next()){var c=p.value;c.remove(this)}}catch(M){t={error:M}}finally{try{p&&!p.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var l=this.initialTeardown;if(H(l))try{l()}catch(M){i=M instanceof zt?M.errors:[M]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=he(f),d=u.next();!d.done;d=u.next()){var y=d.value;try{uo(y)}catch(M){i=i!=null?i:[],M instanceof zt?i=q(q([],N(i)),N(M.errors)):i.push(M)}}}catch(M){o={error:M}}finally{try{d&&!d.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new zt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)uo(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Qe(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Qe(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Tr=We.EMPTY;function qt(e){return e instanceof We||e&&"closed"in e&&H(e.remove)&&H(e.add)&&H(e.unsubscribe)}function uo(e){H(e)?e():e.unsubscribe()}var Pe={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var dt={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,a=n.isStopped,s=n.observers;return i||a?Tr:(this.currentObservers=null,s.push(r),new We(function(){o.currentObservers=null,Qe(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,a=o.isStopped;n?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new j;return r.source=this,r},t.create=function(r,o){return new wo(r,o)},t}(j);var wo=function(e){oe(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:Tr},t}(g);var _r=function(e){oe(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t}(g);var At={now:function(){return(At.delegate||Date).now()},delegate:void 0};var Ct=function(e){oe(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=At);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,a=o._infiniteTimeWindow,s=o._timestampProvider,p=o._windowTime;n||(i.push(r),!a&&i.push(s.now()+p)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,a=n._buffer,s=a.slice(),p=0;p0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t}(gt);var Oo=function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t}(yt);var kr=new Oo(So);var Mo=function(e){oe(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=vt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var a=r.actions;o!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==o&&(vt.cancelAnimationFrame(o),r._scheduled=void 0)},t}(gt);var Lo=function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(yt);var me=new Lo(Mo);var S=new j(function(e){return e.complete()});function Yt(e){return e&&H(e.schedule)}function Hr(e){return e[e.length-1]}function Xe(e){return H(Hr(e))?e.pop():void 0}function ke(e){return Yt(Hr(e))?e.pop():void 0}function Bt(e,t){return typeof Hr(e)=="number"?e.pop():t}var xt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Gt(e){return H(e==null?void 0:e.then)}function Jt(e){return H(e[bt])}function Xt(e){return Symbol.asyncIterator&&H(e==null?void 0:e[Symbol.asyncIterator])}function Zt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ji(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var er=Ji();function tr(e){return H(e==null?void 0:e[er])}function rr(e){return mo(this,arguments,function(){var r,o,n,i;return Nt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,nt(r.read())];case 3:return o=a.sent(),n=o.value,i=o.done,i?[4,nt(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,nt(n)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function or(e){return H(e==null?void 0:e.getReader)}function W(e){if(e instanceof j)return e;if(e!=null){if(Jt(e))return Xi(e);if(xt(e))return Zi(e);if(Gt(e))return ea(e);if(Xt(e))return _o(e);if(tr(e))return ta(e);if(or(e))return ra(e)}throw Zt(e)}function Xi(e){return new j(function(t){var r=e[bt]();if(H(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Zi(e){return new j(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?b(function(n,i){return e(n,i,o)}):le,Te(1),r?De(t):qo(function(){return new ir}))}}function jr(e){return e<=0?function(){return S}:E(function(t,r){var o=[];t.subscribe(T(r,function(n){o.push(n),e=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new g}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,p=s===void 0?!0:s;return function(c){var l,f,u,d=0,y=!1,M=!1,X=function(){f==null||f.unsubscribe(),f=void 0},te=function(){X(),l=u=void 0,y=M=!1},J=function(){var k=l;te(),k==null||k.unsubscribe()};return E(function(k,ft){d++,!M&&!y&&X();var qe=u=u!=null?u:r();ft.add(function(){d--,d===0&&!M&&!y&&(f=Wr(J,p))}),qe.subscribe(ft),!l&&d>0&&(l=new at({next:function(Fe){return qe.next(Fe)},error:function(Fe){M=!0,X(),f=Wr(te,n,Fe),qe.error(Fe)},complete:function(){y=!0,X(),f=Wr(te,a),qe.complete()}}),W(k).subscribe(l))})(c)}}function Wr(e,t){for(var r=[],o=2;oe.next(document)),e}function P(e,t=document){return Array.from(t.querySelectorAll(e))}function R(e,t=document){let r=fe(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function fe(e,t=document){return t.querySelector(e)||void 0}function Ie(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var xa=O(h(document.body,"focusin"),h(document.body,"focusout")).pipe(_e(1),Q(void 0),m(()=>Ie()||document.body),G(1));function et(e){return xa.pipe(m(t=>e.contains(t)),K())}function $t(e,t){return C(()=>O(h(e,"mouseenter").pipe(m(()=>!0)),h(e,"mouseleave").pipe(m(()=>!1))).pipe(t?Ht(r=>Me(+!r*t)):le,Q(e.matches(":hover"))))}function Go(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)Go(e,r)}function x(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)Go(o,n);return o}function sr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function Tt(e){let t=x("script",{src:e});return C(()=>(document.head.appendChild(t),O(h(t,"load"),h(t,"error").pipe(v(()=>$r(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),_(()=>document.head.removeChild(t)),Te(1))))}var Jo=new g,Ea=C(()=>typeof ResizeObserver=="undefined"?Tt("https://unpkg.com/resize-observer-polyfill"):I(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>Jo.next(t)))),v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function ce(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return Ea.pipe(w(r=>r.observe(t)),v(r=>Jo.pipe(b(o=>o.target===t),_(()=>r.unobserve(t)))),m(()=>ce(e)),Q(ce(e)))}function St(e){return{width:e.scrollWidth,height:e.scrollHeight}}function cr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function Xo(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function Ve(e){return{x:e.offsetLeft,y:e.offsetTop}}function Zo(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function en(e){return O(h(window,"load"),h(window,"resize")).pipe(Le(0,me),m(()=>Ve(e)),Q(Ve(e)))}function pr(e){return{x:e.scrollLeft,y:e.scrollTop}}function Ne(e){return O(h(e,"scroll"),h(window,"scroll"),h(window,"resize")).pipe(Le(0,me),m(()=>pr(e)),Q(pr(e)))}var tn=new g,wa=C(()=>I(new IntersectionObserver(e=>{for(let t of e)tn.next(t)},{threshold:0}))).pipe(v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function tt(e){return wa.pipe(w(t=>t.observe(e)),v(t=>tn.pipe(b(({target:r})=>r===e),_(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function rn(e,t=16){return Ne(e).pipe(m(({y:r})=>{let o=ce(e),n=St(e);return r>=n.height-o.height-t}),K())}var lr={drawer:R("[data-md-toggle=drawer]"),search:R("[data-md-toggle=search]")};function on(e){return lr[e].checked}function Je(e,t){lr[e].checked!==t&&lr[e].click()}function ze(e){let t=lr[e];return h(t,"change").pipe(m(()=>t.checked),Q(t.checked))}function Ta(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Sa(){return O(h(window,"compositionstart").pipe(m(()=>!0)),h(window,"compositionend").pipe(m(()=>!1))).pipe(Q(!1))}function nn(){let e=h(window,"keydown").pipe(b(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:on("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),b(({mode:t,type:r})=>{if(t==="global"){let o=Ie();if(typeof o!="undefined")return!Ta(o,r)}return!0}),pe());return Sa().pipe(v(t=>t?S:e))}function ye(){return new URL(location.href)}function lt(e,t=!1){if(B("navigation.instant")&&!t){let r=x("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function an(){return new g}function sn(){return location.hash.slice(1)}function cn(e){let t=x("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Oa(e){return O(h(window,"hashchange"),e).pipe(m(sn),Q(sn()),b(t=>t.length>0),G(1))}function pn(e){return Oa(e).pipe(m(t=>fe(`[id="${t}"]`)),b(t=>typeof t!="undefined"))}function Pt(e){let t=matchMedia(e);return ar(r=>t.addListener(()=>r(t.matches))).pipe(Q(t.matches))}function ln(){let e=matchMedia("print");return O(h(window,"beforeprint").pipe(m(()=>!0)),h(window,"afterprint").pipe(m(()=>!1))).pipe(Q(e.matches))}function Nr(e,t){return e.pipe(v(r=>r?t():S))}function zr(e,t){return new j(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let a=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+a*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function je(e,t){return zr(e,t).pipe(v(r=>r.text()),m(r=>JSON.parse(r)),G(1))}function mn(e,t){let r=new DOMParser;return zr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),G(1))}function fn(e,t){let r=new DOMParser;return zr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),G(1))}function un(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function dn(){return O(h(window,"scroll",{passive:!0}),h(window,"resize",{passive:!0})).pipe(m(un),Q(un()))}function hn(){return{width:innerWidth,height:innerHeight}}function bn(){return h(window,"resize",{passive:!0}).pipe(m(hn),Q(hn()))}function vn(){return z([dn(),bn()]).pipe(m(([e,t])=>({offset:e,size:t})),G(1))}function mr(e,{viewport$:t,header$:r}){let o=t.pipe(ee("size")),n=z([o,r]).pipe(m(()=>Ve(e)));return z([r,t,n]).pipe(m(([{height:i},{offset:a,size:s},{x:p,y:c}])=>({offset:{x:a.x-p,y:a.y-c+i},size:s})))}function Ma(e){return h(e,"message",t=>t.data)}function La(e){let t=new g;return t.subscribe(r=>e.postMessage(r)),t}function gn(e,t=new Worker(e)){let r=Ma(t),o=La(t),n=new g;n.subscribe(o);let i=o.pipe(Z(),ie(!0));return n.pipe(Z(),Re(r.pipe(U(i))),pe())}var _a=R("#__config"),Ot=JSON.parse(_a.textContent);Ot.base=`${new URL(Ot.base,ye())}`;function xe(){return Ot}function B(e){return Ot.features.includes(e)}function Ee(e,t){return typeof t!="undefined"?Ot.translations[e].replace("#",t.toString()):Ot.translations[e]}function Se(e,t=document){return R(`[data-md-component=${e}]`,t)}function ae(e,t=document){return P(`[data-md-component=${e}]`,t)}function Aa(e){let t=R(".md-typeset > :first-child",e);return h(t,"click",{once:!0}).pipe(m(()=>R(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function yn(e){if(!B("announce.dismiss")||!e.childElementCount)return S;if(!e.hidden){let t=R(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return C(()=>{let t=new g;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),Aa(e).pipe(w(r=>t.next(r)),_(()=>t.complete()),m(r=>$({ref:e},r)))})}function Ca(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function xn(e,t){let r=new g;return r.subscribe(({hidden:o})=>{e.hidden=o}),Ca(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))}function Rt(e,t){return t==="inline"?x("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"})):x("div",{class:"md-tooltip",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"}))}function En(...e){return x("div",{class:"md-tooltip2",role:"tooltip"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function wn(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return x("aside",{class:"md-annotation",tabIndex:0},Rt(t),x("a",{href:r,class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}else return x("aside",{class:"md-annotation",tabIndex:0},Rt(t),x("span",{class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}function Tn(e){return x("button",{class:"md-clipboard md-icon",title:Ee("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}var On=Lt(qr());function Qr(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(p=>!e.terms[p]).reduce((p,c)=>[...p,x("del",null,(0,On.default)(c))," "],[]).slice(0,-1),i=xe(),a=new URL(e.location,i.base);B("search.highlight")&&a.searchParams.set("h",Object.entries(e.terms).filter(([,p])=>p).reduce((p,[c])=>`${p} ${c}`.trim(),""));let{tags:s}=xe();return x("a",{href:`${a}`,class:"md-search-result__link",tabIndex:-1},x("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&x("div",{class:"md-search-result__icon md-icon"}),r>0&&x("h1",null,e.title),r<=0&&x("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&e.tags.map(p=>{let c=s?p in s?`md-tag-icon md-tag--${s[p]}`:"md-tag-icon":"";return x("span",{class:`md-tag ${c}`},p)}),o>0&&n.length>0&&x("p",{class:"md-search-result__terms"},Ee("search.result.term.missing"),": ",...n)))}function Mn(e){let t=e[0].score,r=[...e],o=xe(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),a=r.findIndex(l=>l.scoreQr(l,1)),...p.length?[x("details",{class:"md-search-result__more"},x("summary",{tabIndex:-1},x("div",null,p.length>0&&p.length===1?Ee("search.result.more.one"):Ee("search.result.more.other",p.length))),...p.map(l=>Qr(l,1)))]:[]];return x("li",{class:"md-search-result__item"},c)}function Ln(e){return x("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>x("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?sr(r):r)))}function Kr(e){let t=`tabbed-control tabbed-control--${e}`;return x("div",{class:t,hidden:!0},x("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function _n(e){return x("div",{class:"md-typeset__scrollwrap"},x("div",{class:"md-typeset__table"},e))}function $a(e){var o;let t=xe(),r=new URL(`../${e.version}/`,t.base);return x("li",{class:"md-version__item"},x("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&x("span",{class:"md-version__alias"},e.aliases[0])))}function An(e,t){var o;let r=xe();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),x("div",{class:"md-version"},x("button",{class:"md-version__current","aria-label":Ee("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&x("span",{class:"md-version__alias"},t.aliases[0])),x("ul",{class:"md-version__list"},e.map($a)))}var Pa=0;function Ra(e){let t=z([et(e),$t(e)]).pipe(m(([o,n])=>o||n),K()),r=C(()=>Xo(e)).pipe(ne(Ne),pt(1),He(t),m(()=>Zo(e)));return t.pipe(Ae(o=>o),v(()=>z([t,r])),m(([o,n])=>({active:o,offset:n})),pe())}function Ia(e,t){let{content$:r,viewport$:o}=t,n=`__tooltip2_${Pa++}`;return C(()=>{let i=new g,a=new _r(!1);i.pipe(Z(),ie(!1)).subscribe(a);let s=a.pipe(Ht(c=>Me(+!c*250,kr)),K(),v(c=>c?r:S),w(c=>c.id=n),pe());z([i.pipe(m(({active:c})=>c)),s.pipe(v(c=>$t(c,250)),Q(!1))]).pipe(m(c=>c.some(l=>l))).subscribe(a);let p=a.pipe(b(c=>c),re(s,o),m(([c,l,{size:f}])=>{let u=e.getBoundingClientRect(),d=u.width/2;if(l.role==="tooltip")return{x:d,y:8+u.height};if(u.y>=f.height/2){let{height:y}=ce(l);return{x:d,y:-16-y}}else return{x:d,y:16+u.height}}));return z([s,i,p]).subscribe(([c,{offset:l},f])=>{c.style.setProperty("--md-tooltip-host-x",`${l.x}px`),c.style.setProperty("--md-tooltip-host-y",`${l.y}px`),c.style.setProperty("--md-tooltip-x",`${f.x}px`),c.style.setProperty("--md-tooltip-y",`${f.y}px`),c.classList.toggle("md-tooltip2--top",f.y<0),c.classList.toggle("md-tooltip2--bottom",f.y>=0)}),a.pipe(b(c=>c),re(s,(c,l)=>l),b(c=>c.role==="tooltip")).subscribe(c=>{let l=ce(R(":scope > *",c));c.style.setProperty("--md-tooltip-width",`${l.width}px`),c.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(K(),ve(me),re(s)).subscribe(([c,l])=>{l.classList.toggle("md-tooltip2--active",c)}),z([a.pipe(b(c=>c)),s]).subscribe(([c,l])=>{l.role==="dialog"?(e.setAttribute("aria-controls",n),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",n)}),a.pipe(b(c=>!c)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),Ra(e).pipe(w(c=>i.next(c)),_(()=>i.complete()),m(c=>$({ref:e},c)))})}function mt(e,{viewport$:t},r=document.body){return Ia(e,{content$:new j(o=>{let n=e.title,i=En(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t})}function ja(e,t){let r=C(()=>z([en(e),Ne(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:a,height:s}=ce(e);return{x:o-i.x+a/2,y:n-i.y+s/2}}));return et(e).pipe(v(o=>r.pipe(m(n=>({active:o,offset:n})),Te(+!o||1/0))))}function Cn(e,t,{target$:r}){let[o,n]=Array.from(e.children);return C(()=>{let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),tt(e).pipe(U(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),O(i.pipe(b(({active:s})=>s)),i.pipe(_e(250),b(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe(Le(16,me)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),h(n,"click").pipe(U(a),b(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),h(n,"mousedown").pipe(U(a),re(i)).subscribe(([s,{active:p}])=>{var c;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(p){s.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(c=Ie())==null||c.blur()}}),r.pipe(U(a),b(s=>s===o),Ge(125)).subscribe(()=>e.focus()),ja(e,t).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function Fa(e){return e.tagName==="CODE"?P(".c, .c1, .cm",e):[e]}function Wa(e){let t=[];for(let r of Fa(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,p]=a;if(typeof p=="undefined"){let c=i.splitText(a.index);i=c.splitText(s.length),t.push(c)}else{i.textContent=s,t.push(i);break}}}}return t}function kn(e,t){t.append(...Array.from(e.childNodes))}function fr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,a=new Map;for(let s of Wa(t)){let[,p]=s.textContent.match(/\((\d+)\)/);fe(`:scope > li:nth-child(${p})`,e)&&(a.set(p,wn(p,i)),s.replaceWith(a.get(p)))}return a.size===0?S:C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=[];for(let[l,f]of a)c.push([R(".md-typeset",f),R(`:scope > li:nth-child(${l})`,e)]);return o.pipe(U(p)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of c)l?kn(f,u):kn(u,f)}),O(...[...a].map(([,l])=>Cn(l,t,{target$:r}))).pipe(_(()=>s.complete()),pe())})}function Hn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Hn(t)}}function $n(e,t){return C(()=>{let r=Hn(e);return typeof r!="undefined"?fr(r,e,t):S})}var Pn=Lt(Br());var Ua=0;function Rn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Rn(t)}}function Da(e){return ge(e).pipe(m(({width:t})=>({scrollable:St(e).width>t})),ee("scrollable"))}function In(e,t){let{matches:r}=matchMedia("(hover)"),o=C(()=>{let n=new g,i=n.pipe(jr(1));n.subscribe(({scrollable:c})=>{c&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[];if(Pn.default.isSupported()&&(e.closest(".copy")||B("content.code.copy")&&!e.closest(".no-copy"))){let c=e.closest("pre");c.id=`__code_${Ua++}`;let l=Tn(c.id);c.insertBefore(l,e),B("content.tooltips")&&a.push(mt(l,{viewport$}))}let s=e.closest(".highlight");if(s instanceof HTMLElement){let c=Rn(s);if(typeof c!="undefined"&&(s.classList.contains("annotate")||B("content.code.annotate"))){let l=fr(c,e,t);a.push(ge(s).pipe(U(i),m(({width:f,height:u})=>f&&u),K(),v(f=>f?l:S)))}}return P(":scope > span[id]",e).length&&e.classList.add("md-code__content"),Da(e).pipe(w(c=>n.next(c)),_(()=>n.complete()),m(c=>$({ref:e},c)),Re(...a))});return B("content.lazy")?tt(e).pipe(b(n=>n),Te(1),v(()=>o)):o}function Va(e,{target$:t,print$:r}){let o=!0;return O(t.pipe(m(n=>n.closest("details:not([open])")),b(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(b(n=>n||!o),w(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function jn(e,t){return C(()=>{let r=new g;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),Va(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}var Fn=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var Gr,za=0;function qa(){return typeof mermaid=="undefined"||mermaid instanceof Element?Tt("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):I(void 0)}function Wn(e){return e.classList.remove("mermaid"),Gr||(Gr=qa().pipe(w(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Fn,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),G(1))),Gr.subscribe(()=>so(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${za++}`,r=x("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),a=r.attachShadow({mode:"closed"});a.innerHTML=n,e.replaceWith(r),i==null||i(a)})),Gr.pipe(m(()=>({ref:e})))}var Un=x("table");function Dn(e){return e.replaceWith(Un),Un.replaceWith(_n(e)),I({ref:e})}function Qa(e){let t=e.find(r=>r.checked)||e[0];return O(...e.map(r=>h(r,"change").pipe(m(()=>R(`label[for="${r.id}"]`))))).pipe(Q(R(`label[for="${t.id}"]`)),m(r=>({active:r})))}function Vn(e,{viewport$:t,target$:r}){let o=R(".tabbed-labels",e),n=P(":scope > input",e),i=Kr("prev");e.append(i);let a=Kr("next");return e.append(a),C(()=>{let s=new g,p=s.pipe(Z(),ie(!0));z([s,ge(e),tt(e)]).pipe(U(p),Le(1,me)).subscribe({next([{active:c},l]){let f=Ve(c),{width:u}=ce(c);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let d=pr(o);(f.xd.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),z([Ne(o),ge(o)]).pipe(U(p)).subscribe(([c,l])=>{let f=St(o);i.hidden=c.x<16,a.hidden=c.x>f.width-l.width-16}),O(h(i,"click").pipe(m(()=>-1)),h(a,"click").pipe(m(()=>1))).pipe(U(p)).subscribe(c=>{let{width:l}=ce(o);o.scrollBy({left:l*c,behavior:"smooth"})}),r.pipe(U(p),b(c=>n.includes(c))).subscribe(c=>c.click()),o.classList.add("tabbed-labels--linked");for(let c of n){let l=R(`label[for="${c.id}"]`);l.replaceChildren(x("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),h(l.firstElementChild,"click").pipe(U(p),b(f=>!(f.metaKey||f.ctrlKey)),w(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return B("content.tabs.link")&&s.pipe(Ce(1),re(t)).subscribe(([{active:c},{offset:l}])=>{let f=c.innerText.trim();if(c.hasAttribute("data-md-switching"))c.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let y of P("[data-tabs]"))for(let M of P(":scope > input",y)){let X=R(`label[for="${M.id}"]`);if(X!==c&&X.innerText.trim()===f){X.setAttribute("data-md-switching",""),M.click();break}}window.scrollTo({top:e.offsetTop-u});let d=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...d])])}}),s.pipe(U(p)).subscribe(()=>{for(let c of P("audio, video",e))c.pause()}),Qa(n).pipe(w(c=>s.next(c)),_(()=>s.complete()),m(c=>$({ref:e},c)))}).pipe(Ke(se))}function Nn(e,{viewport$:t,target$:r,print$:o}){return O(...P(".annotate:not(.highlight)",e).map(n=>$n(n,{target$:r,print$:o})),...P("pre:not(.mermaid) > code",e).map(n=>In(n,{target$:r,print$:o})),...P("pre.mermaid",e).map(n=>Wn(n)),...P("table:not([class])",e).map(n=>Dn(n)),...P("details",e).map(n=>jn(n,{target$:r,print$:o})),...P("[data-tabs]",e).map(n=>Vn(n,{viewport$:t,target$:r})),...P("[title]",e).filter(()=>B("content.tooltips")).map(n=>mt(n,{viewport$:t})))}function Ka(e,{alert$:t}){return t.pipe(v(r=>O(I(!0),I(!1).pipe(Ge(2e3))).pipe(m(o=>({message:r,active:o})))))}function zn(e,t){let r=R(".md-typeset",e);return C(()=>{let o=new g;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),Ka(e,t).pipe(w(n=>o.next(n)),_(()=>o.complete()),m(n=>$({ref:e},n)))})}var Ya=0;function Ba(e,t){document.body.append(e);let{width:r}=ce(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=cr(t),n=typeof o!="undefined"?Ne(o):I({x:0,y:0}),i=O(et(t),$t(t)).pipe(K());return z([i,n]).pipe(m(([a,s])=>{let{x:p,y:c}=Ve(t),l=ce(t),f=t.closest("table");return f&&t.parentElement&&(p+=f.offsetLeft+t.parentElement.offsetLeft,c+=f.offsetTop+t.parentElement.offsetTop),{active:a,offset:{x:p-s.x+l.width/2-r/2,y:c-s.y+l.height+8}}}))}function qn(e){let t=e.title;if(!t.length)return S;let r=`__tooltip_${Ya++}`,o=Rt(r,"inline"),n=R(".md-typeset",o);return n.innerHTML=t,C(()=>{let i=new g;return i.subscribe({next({offset:a}){o.style.setProperty("--md-tooltip-x",`${a.x}px`),o.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),O(i.pipe(b(({active:a})=>a)),i.pipe(_e(250),b(({active:a})=>!a))).subscribe({next({active:a}){a?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe(Le(16,me)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?o.style.setProperty("--md-tooltip-0",`${-a}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),Ba(o,e).pipe(w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))}).pipe(Ke(se))}function Ga({viewport$:e}){if(!B("header.autohide"))return I(!1);let t=e.pipe(m(({offset:{y:n}})=>n),Be(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),K()),o=ze("search");return z([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),K(),v(n=>n?r:I(!1)),Q(!1))}function Qn(e,t){return C(()=>z([ge(e),Ga(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),K((r,o)=>r.height===o.height&&r.hidden===o.hidden),G(1))}function Kn(e,{header$:t,main$:r}){return C(()=>{let o=new g,n=o.pipe(Z(),ie(!0));o.pipe(ee("active"),He(t)).subscribe(([{active:a},{hidden:s}])=>{e.classList.toggle("md-header--shadow",a&&!s),e.hidden=s});let i=ue(P("[title]",e)).pipe(b(()=>B("content.tooltips")),ne(a=>qn(a)));return r.subscribe(o),t.pipe(U(n),m(a=>$({ref:e},a)),Re(i.pipe(U(n))))})}function Ja(e,{viewport$:t,header$:r}){return mr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=ce(e);return{active:o>=n}}),ee("active"))}function Yn(e,t){return C(()=>{let r=new g;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=fe(".md-content h1");return typeof o=="undefined"?S:Ja(o,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))})}function Bn(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),K()),n=o.pipe(v(()=>ge(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),ee("bottom"))));return z([o,n,t]).pipe(m(([i,{top:a,bottom:s},{offset:{y:p},size:{height:c}}])=>(c=Math.max(0,c-Math.max(0,a-p,i)-Math.max(0,c+p-s)),{offset:a-i,height:c,active:a-i<=p})),K((i,a)=>i.offset===a.offset&&i.height===a.height&&i.active===a.active))}function Xa(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return I(...e).pipe(ne(o=>h(o,"change").pipe(m(()=>o))),Q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),G(1))}function Gn(e){let t=P("input",e),r=x("meta",{name:"theme-color"});document.head.appendChild(r);let o=x("meta",{name:"color-scheme"});document.head.appendChild(o);let n=Pt("(prefers-color-scheme: light)");return C(()=>{let i=new g;return i.subscribe(a=>{if(document.body.setAttribute("data-md-color-switching",""),a.color.media==="(prefers-color-scheme)"){let s=matchMedia("(prefers-color-scheme: light)"),p=document.querySelector(s.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");a.color.scheme=p.getAttribute("data-md-color-scheme"),a.color.primary=p.getAttribute("data-md-color-primary"),a.color.accent=p.getAttribute("data-md-color-accent")}for(let[s,p]of Object.entries(a.color))document.body.setAttribute(`data-md-color-${s}`,p);for(let s=0;sa.key==="Enter"),re(i,(a,s)=>s)).subscribe(({index:a})=>{a=(a+1)%t.length,t[a].click(),t[a].focus()}),i.pipe(m(()=>{let a=Se("header"),s=window.getComputedStyle(a);return o.content=s.colorScheme,s.backgroundColor.match(/\d+/g).map(p=>(+p).toString(16).padStart(2,"0")).join("")})).subscribe(a=>r.content=`#${a}`),i.pipe(ve(se)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),Xa(t).pipe(U(n.pipe(Ce(1))),ct(),w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))})}function Jn(e,{progress$:t}){return C(()=>{let r=new g;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(w(o=>r.next({value:o})),_(()=>r.complete()),m(o=>({ref:e,value:o})))})}var Jr=Lt(Br());function Za(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function Xn({alert$:e}){Jr.default.isSupported()&&new j(t=>{new Jr.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||Za(R(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(w(t=>{t.trigger.focus()}),m(()=>Ee("clipboard.copied"))).subscribe(e)}function Zn(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function es(e,t){let r=new Map;for(let o of P("url",e)){let n=R("loc",o),i=[Zn(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let a of P("[rel=alternate]",o)){let s=a.getAttribute("href");s!=null&&i.push(Zn(new URL(s),t))}}return r}function ur(e){return fn(new URL("sitemap.xml",e)).pipe(m(t=>es(t,new URL(e))),de(()=>I(new Map)))}function ts(e,t){if(!(e.target instanceof Element))return S;let r=e.target.closest("a");if(r===null)return S;if(r.target||e.metaKey||e.ctrlKey)return S;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),I(new URL(r.href))):S}function ei(e){let t=new Map;for(let r of P(":scope > *",e.head))t.set(r.outerHTML,r);return t}function ti(e){for(let t of P("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return I(e)}function rs(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...B("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=fe(o),i=fe(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=ei(document);for(let[o,n]of ei(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Se("container");return Ue(P("script",r)).pipe(v(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new j(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),S}),Z(),ie(document))}function ri({location$:e,viewport$:t,progress$:r}){let o=xe();if(location.protocol==="file:")return S;let n=ur(o.base);I(document).subscribe(ti);let i=h(document.body,"click").pipe(He(n),v(([p,c])=>ts(p,c)),pe()),a=h(window,"popstate").pipe(m(ye),pe());i.pipe(re(t)).subscribe(([p,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",p)}),O(i,a).subscribe(e);let s=e.pipe(ee("pathname"),v(p=>mn(p,{progress$:r}).pipe(de(()=>(lt(p,!0),S)))),v(ti),v(rs),pe());return O(s.pipe(re(e,(p,c)=>c)),s.pipe(v(()=>e),ee("pathname"),v(()=>e),ee("hash")),e.pipe(K((p,c)=>p.pathname===c.pathname&&p.hash===c.hash),v(()=>i),w(()=>history.back()))).subscribe(p=>{var c,l;history.state!==null||!p.hash?window.scrollTo(0,(l=(c=history.state)==null?void 0:c.y)!=null?l:0):(history.scrollRestoration="auto",cn(p.hash),history.scrollRestoration="manual")}),e.subscribe(()=>{history.scrollRestoration="manual"}),h(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),t.pipe(ee("offset"),_e(100)).subscribe(({offset:p})=>{history.replaceState(p,"")}),s}var oi=Lt(qr());function ni(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,a)=>`${i}${a}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return a=>(0,oi.default)(a).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function jt(e){return e.type===1}function dr(e){return e.type===3}function ii(e,t){let r=gn(e);return O(I(location.protocol!=="file:"),ze("search")).pipe(Ae(o=>o),v(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:B("search.suggest")}}})),r}function ai({document$:e}){let t=xe(),r=je(new URL("../versions.json",t.base)).pipe(de(()=>S)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:a,aliases:s})=>a===i||s.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),v(n=>h(document.body,"click").pipe(b(i=>!i.metaKey&&!i.ctrlKey),re(o),v(([i,a])=>{if(i.target instanceof Element){let s=i.target.closest("a");if(s&&!s.target&&n.has(s.href)){let p=s.href;return!i.target.closest(".md-version")&&n.get(p)===a?S:(i.preventDefault(),I(p))}}return S}),v(i=>ur(new URL(i)).pipe(m(a=>{let p=ye().href.replace(t.base,i);return a.has(p.split("#")[0])?new URL(p):new URL(i)})))))).subscribe(n=>lt(n,!0)),z([r,o]).subscribe(([n,i])=>{R(".md-header__topic").appendChild(An(n,i))}),e.pipe(v(()=>o)).subscribe(n=>{var a;let i=__md_get("__outdated",sessionStorage);if(i===null){i=!0;let s=((a=t.version)==null?void 0:a.default)||"latest";Array.isArray(s)||(s=[s]);e:for(let p of s)for(let c of n.aliases.concat(n.version))if(new RegExp(p,"i").test(c)){i=!1;break e}__md_set("__outdated",i,sessionStorage)}if(i)for(let s of ae("outdated"))s.hidden=!1})}function is(e,{worker$:t}){let{searchParams:r}=ye();r.has("q")&&(Je("search",!0),e.value=r.get("q"),e.focus(),ze("search").pipe(Ae(i=>!i)).subscribe(()=>{let i=ye();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=et(e),n=O(t.pipe(Ae(jt)),h(e,"keyup"),o).pipe(m(()=>e.value),K());return z([n,o]).pipe(m(([i,a])=>({value:i,focus:a})),G(1))}function si(e,{worker$:t}){let r=new g,o=r.pipe(Z(),ie(!0));z([t.pipe(Ae(jt)),r],(i,a)=>a).pipe(ee("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(ee("focus")).subscribe(({focus:i})=>{i&&Je("search",i)}),h(e.form,"reset").pipe(U(o)).subscribe(()=>e.focus());let n=R("header [for=__search]");return h(n,"click").subscribe(()=>e.focus()),is(e,{worker$:t}).pipe(w(i=>r.next(i)),_(()=>r.complete()),m(i=>$({ref:e},i)),G(1))}function ci(e,{worker$:t,query$:r}){let o=new g,n=rn(e.parentElement).pipe(b(Boolean)),i=e.parentElement,a=R(":scope > :first-child",e),s=R(":scope > :last-child",e);ze("search").subscribe(l=>s.setAttribute("role",l?"list":"presentation")),o.pipe(re(r),Ur(t.pipe(Ae(jt)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:a.textContent=f.length?Ee("search.result.none"):Ee("search.result.placeholder");break;case 1:a.textContent=Ee("search.result.one");break;default:let u=sr(l.length);a.textContent=Ee("search.result.other",u)}});let p=o.pipe(w(()=>s.innerHTML=""),v(({items:l})=>O(I(...l.slice(0,10)),I(...l.slice(10)).pipe(Be(4),Vr(n),v(([f])=>f)))),m(Mn),pe());return p.subscribe(l=>s.appendChild(l)),p.pipe(ne(l=>{let f=fe("details",l);return typeof f=="undefined"?S:h(f,"toggle").pipe(U(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(b(dr),m(({data:l})=>l)).pipe(w(l=>o.next(l)),_(()=>o.complete()),m(l=>$({ref:e},l)))}function as(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=ye();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function pi(e,t){let r=new g,o=r.pipe(Z(),ie(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),h(e,"click").pipe(U(o)).subscribe(n=>n.preventDefault()),as(e,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))}function li(e,{worker$:t,keyboard$:r}){let o=new g,n=Se("search-query"),i=O(h(n,"keydown"),h(n,"focus")).pipe(ve(se),m(()=>n.value),K());return o.pipe(He(i),m(([{suggest:s},p])=>{let c=p.split(/([\s-]+)/);if(s!=null&&s.length&&c[c.length-1]){let l=s[s.length-1];l.startsWith(c[c.length-1])&&(c[c.length-1]=l)}else c.length=0;return c})).subscribe(s=>e.innerHTML=s.join("").replace(/\s/g," ")),r.pipe(b(({mode:s})=>s==="search")).subscribe(s=>{switch(s.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(b(dr),m(({data:s})=>s)).pipe(w(s=>o.next(s)),_(()=>o.complete()),m(()=>({ref:e})))}function mi(e,{index$:t,keyboard$:r}){let o=xe();try{let n=ii(o.search,t),i=Se("search-query",e),a=Se("search-result",e);h(e,"click").pipe(b(({target:p})=>p instanceof Element&&!!p.closest("a"))).subscribe(()=>Je("search",!1)),r.pipe(b(({mode:p})=>p==="search")).subscribe(p=>{let c=Ie();switch(p.type){case"Enter":if(c===i){let l=new Map;for(let f of P(":first-child [href]",a)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,d])=>d-u);f.click()}p.claim()}break;case"Escape":case"Tab":Je("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof c=="undefined")i.focus();else{let l=[i,...P(":not(details) > [href], summary, details[open] [href]",a)],f=Math.max(0,(Math.max(0,l.indexOf(c))+l.length+(p.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}p.claim();break;default:i!==Ie()&&i.focus()}}),r.pipe(b(({mode:p})=>p==="global")).subscribe(p=>{switch(p.type){case"f":case"s":case"/":i.focus(),i.select(),p.claim();break}});let s=si(i,{worker$:n});return O(s,ci(a,{worker$:n,query$:s})).pipe(Re(...ae("search-share",e).map(p=>pi(p,{query$:s})),...ae("search-suggest",e).map(p=>li(p,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,Ye}}function fi(e,{index$:t,location$:r}){return z([t,r.pipe(Q(ye()),b(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>ni(o.config)(n.searchParams.get("h"))),m(o=>{var a;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let s=i.nextNode();s;s=i.nextNode())if((a=s.parentElement)!=null&&a.offsetHeight){let p=s.textContent,c=o(p);c.length>p.length&&n.set(s,c)}for(let[s,p]of n){let{childNodes:c}=x("span",null,p);s.replaceWith(...Array.from(c))}return{ref:e,nodes:n}}))}function ss(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return z([r,t]).pipe(m(([{offset:i,height:a},{offset:{y:s}}])=>(a=a+Math.min(n,Math.max(0,s-i))-n,{height:a,locked:s>=i+n})),K((i,a)=>i.height===a.height&&i.locked===a.locked))}function Xr(e,o){var n=o,{header$:t}=n,r=ao(n,["header$"]);let i=R(".md-sidebar__scrollwrap",e),{y:a}=Ve(i);return C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=s.pipe(Le(0,me));return c.pipe(re(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*a}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),c.pipe(Ae()).subscribe(()=>{for(let l of P(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2})}}}),ue(P("label[tabindex]",e)).pipe(ne(l=>h(l,"click").pipe(ve(se),m(()=>l),U(p)))).subscribe(l=>{let f=R(`[id="${l.htmlFor}"]`);R(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),ss(e,r).pipe(w(l=>s.next(l)),_(()=>s.complete()),m(l=>$({ref:e},l)))})}function ui(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return st(je(`${r}/releases/latest`).pipe(de(()=>S),m(o=>({version:o.tag_name})),De({})),je(r).pipe(de(()=>S),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),De({}))).pipe(m(([o,n])=>$($({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return je(r).pipe(m(o=>({repositories:o.public_repos})),De({}))}}function di(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return st(je(`${r}/releases/permalink/latest`).pipe(de(()=>S),m(({tag_name:o})=>({version:o})),De({})),je(r).pipe(de(()=>S),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),De({}))).pipe(m(([o,n])=>$($({},o),n)))}function hi(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return ui(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return di(r,o)}return S}var cs;function ps(e){return cs||(cs=C(()=>{let t=__md_get("__source",sessionStorage);if(t)return I(t);if(ae("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return S}return hi(e.href).pipe(w(o=>__md_set("__source",o,sessionStorage)))}).pipe(de(()=>S),b(t=>Object.keys(t).length>0),m(t=>({facts:t})),G(1)))}function bi(e){let t=R(":scope > :last-child",e);return C(()=>{let r=new g;return r.subscribe(({facts:o})=>{t.appendChild(Ln(o)),t.classList.add("md-source__repository--active")}),ps(e).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function ls(e,{viewport$:t,header$:r}){return ge(document.body).pipe(v(()=>mr(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),ee("hidden"))}function vi(e,t){return C(()=>{let r=new g;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(B("navigation.tabs.sticky")?I({hidden:!1}):ls(e,t)).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function ms(e,{viewport$:t,header$:r}){let o=new Map,n=P(".md-nav__link",e);for(let s of n){let p=decodeURIComponent(s.hash.substring(1)),c=fe(`[id="${p}"]`);typeof c!="undefined"&&o.set(s,c)}let i=r.pipe(ee("height"),m(({height:s})=>{let p=Se("main"),c=R(":scope > :first-child",p);return s+.8*(c.offsetTop-p.offsetTop)}),pe());return ge(document.body).pipe(ee("height"),v(s=>C(()=>{let p=[];return I([...o].reduce((c,[l,f])=>{for(;p.length&&o.get(p[p.length-1]).tagName>=f.tagName;)p.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let d=f.offsetParent;for(;d;d=d.offsetParent)u+=d.offsetTop;return c.set([...p=[...p,l]].reverse(),u)},new Map))}).pipe(m(p=>new Map([...p].sort(([,c],[,l])=>c-l))),He(i),v(([p,c])=>t.pipe(Fr(([l,f],{offset:{y:u},size:d})=>{let y=u+d.height>=Math.floor(s.height);for(;f.length;){let[,M]=f[0];if(M-c=u&&!y)f=[l.pop(),...f];else break}return[l,f]},[[],[...p]]),K((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([s,p])=>({prev:s.map(([c])=>c),next:p.map(([c])=>c)})),Q({prev:[],next:[]}),Be(2,1),m(([s,p])=>s.prev.length{let i=new g,a=i.pipe(Z(),ie(!0));if(i.subscribe(({prev:s,next:p})=>{for(let[c]of p)c.classList.remove("md-nav__link--passed"),c.classList.remove("md-nav__link--active");for(let[c,[l]]of s.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",c===s.length-1)}),B("toc.follow")){let s=O(t.pipe(_e(1),m(()=>{})),t.pipe(_e(250),m(()=>"smooth")));i.pipe(b(({prev:p})=>p.length>0),He(o.pipe(ve(se))),re(s)).subscribe(([[{prev:p}],c])=>{let[l]=p[p.length-1];if(l.offsetHeight){let f=cr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2,behavior:c})}}})}return B("navigation.tracking")&&t.pipe(U(a),ee("offset"),_e(250),Ce(1),U(n.pipe(Ce(1))),ct({delay:250}),re(i)).subscribe(([,{prev:s}])=>{let p=ye(),c=s[s.length-1];if(c&&c.length){let[l]=c,{hash:f}=new URL(l.href);p.hash!==f&&(p.hash=f,history.replaceState({},"",`${p}`))}else p.hash="",history.replaceState({},"",`${p}`)}),ms(e,{viewport$:t,header$:r}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function fs(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:a}})=>a),Be(2,1),m(([a,s])=>a>s&&s>0),K()),i=r.pipe(m(({active:a})=>a));return z([i,n]).pipe(m(([a,s])=>!(a&&s)),K(),U(o.pipe(Ce(1))),ie(!0),ct({delay:250}),m(a=>({hidden:a})))}function yi(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({hidden:s}){e.hidden=s,s?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(U(a),ee("height")).subscribe(({height:s})=>{e.style.top=`${s+16}px`}),h(e,"click").subscribe(s=>{s.preventDefault(),window.scrollTo({top:0})}),fs(e,{viewport$:t,main$:o,target$:n}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))}function xi({document$:e,viewport$:t}){e.pipe(v(()=>P(".md-ellipsis")),ne(r=>tt(r).pipe(U(e.pipe(Ce(1))),b(o=>o),m(()=>r),Te(1))),b(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,B("content.tooltips")?mt(n,{viewport$:t}).pipe(U(e.pipe(Ce(1))),_(()=>n.removeAttribute("title"))):S})).subscribe(),B("content.tooltips")&&e.pipe(v(()=>P(".md-status")),ne(r=>mt(r,{viewport$:t}))).subscribe()}function Ei({document$:e,tablet$:t}){e.pipe(v(()=>P(".md-toggle--indeterminate")),w(r=>{r.indeterminate=!0,r.checked=!1}),ne(r=>h(r,"change").pipe(Dr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),re(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function us(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function wi({document$:e}){e.pipe(v(()=>P("[data-md-scrollfix]")),w(t=>t.removeAttribute("data-md-scrollfix")),b(us),ne(t=>h(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function Ti({viewport$:e,tablet$:t}){z([ze("search"),t]).pipe(m(([r,o])=>r&&!o),v(r=>I(r).pipe(Ge(r?400:100))),re(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function ds(){return location.protocol==="file:"?Tt(`${new URL("search/search_index.js",Zr.base)}`).pipe(m(()=>__index),G(1)):je(new URL("search/search_index.json",Zr.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var ot=Bo(),Wt=an(),Mt=pn(Wt),eo=nn(),Oe=vn(),hr=Pt("(min-width: 960px)"),Oi=Pt("(min-width: 1220px)"),Mi=ln(),Zr=xe(),Li=document.forms.namedItem("search")?ds():Ye,to=new g;Xn({alert$:to});var ro=new g;B("navigation.instant")&&ri({location$:Wt,viewport$:Oe,progress$:ro}).subscribe(ot);var Si;((Si=Zr.version)==null?void 0:Si.provider)==="mike"&&ai({document$:ot});O(Wt,Mt).pipe(Ge(125)).subscribe(()=>{Je("drawer",!1),Je("search",!1)});eo.pipe(b(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=fe("link[rel=prev]");typeof t!="undefined"&<(t);break;case"n":case".":let r=fe("link[rel=next]");typeof r!="undefined"&<(r);break;case"Enter":let o=Ie();o instanceof HTMLLabelElement&&o.click()}});xi({viewport$:Oe,document$:ot});Ei({document$:ot,tablet$:hr});wi({document$:ot});Ti({viewport$:Oe,tablet$:hr});var rt=Qn(Se("header"),{viewport$:Oe}),Ft=ot.pipe(m(()=>Se("main")),v(e=>Bn(e,{viewport$:Oe,header$:rt})),G(1)),hs=O(...ae("consent").map(e=>xn(e,{target$:Mt})),...ae("dialog").map(e=>zn(e,{alert$:to})),...ae("header").map(e=>Kn(e,{viewport$:Oe,header$:rt,main$:Ft})),...ae("palette").map(e=>Gn(e)),...ae("progress").map(e=>Jn(e,{progress$:ro})),...ae("search").map(e=>mi(e,{index$:Li,keyboard$:eo})),...ae("source").map(e=>bi(e))),bs=C(()=>O(...ae("announce").map(e=>yn(e)),...ae("content").map(e=>Nn(e,{viewport$:Oe,target$:Mt,print$:Mi})),...ae("content").map(e=>B("search.highlight")?fi(e,{index$:Li,location$:Wt}):S),...ae("header-title").map(e=>Yn(e,{viewport$:Oe,header$:rt})),...ae("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?Nr(Oi,()=>Xr(e,{viewport$:Oe,header$:rt,main$:Ft})):Nr(hr,()=>Xr(e,{viewport$:Oe,header$:rt,main$:Ft}))),...ae("tabs").map(e=>vi(e,{viewport$:Oe,header$:rt})),...ae("toc").map(e=>gi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Mt})),...ae("top").map(e=>yi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Mt})))),_i=ot.pipe(v(()=>bs),Re(hs),G(1));_i.subscribe();window.document$=ot;window.location$=Wt;window.target$=Mt;window.keyboard$=eo;window.viewport$=Oe;window.tablet$=hr;window.screen$=Oi;window.print$=Mi;window.alert$=to;window.progress$=ro;window.component$=_i;})(); +//# sourceMappingURL=bundle.56dfad97.min.js.map + diff --git a/assets/javascripts/bundle.56dfad97.min.js.map b/assets/javascripts/bundle.56dfad97.min.js.map new file mode 100644 index 0000000..eb83bdb --- /dev/null +++ b/assets/javascripts/bundle.56dfad97.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/escape-html/index.js", "node_modules/clipboard/dist/clipboard.js", "src/templates/assets/javascripts/bundle.ts", "node_modules/tslib/tslib.es6.mjs", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/BehaviorSubject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/QueueAction.ts", "node_modules/rxjs/src/internal/scheduler/QueueScheduler.ts", "node_modules/rxjs/src/internal/scheduler/queue.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/EmptyError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/debounce.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/throwIfEmpty.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/first.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/templates/assets/javascripts/browser/document/index.ts", "src/templates/assets/javascripts/browser/element/_/index.ts", "src/templates/assets/javascripts/browser/element/focus/index.ts", "src/templates/assets/javascripts/browser/element/hover/index.ts", "src/templates/assets/javascripts/utilities/h/index.ts", "src/templates/assets/javascripts/utilities/round/index.ts", "src/templates/assets/javascripts/browser/script/index.ts", "src/templates/assets/javascripts/browser/element/size/_/index.ts", "src/templates/assets/javascripts/browser/element/size/content/index.ts", "src/templates/assets/javascripts/browser/element/offset/_/index.ts", "src/templates/assets/javascripts/browser/element/offset/content/index.ts", "src/templates/assets/javascripts/browser/element/visibility/index.ts", "src/templates/assets/javascripts/browser/toggle/index.ts", "src/templates/assets/javascripts/browser/keyboard/index.ts", "src/templates/assets/javascripts/browser/location/_/index.ts", "src/templates/assets/javascripts/browser/location/hash/index.ts", "src/templates/assets/javascripts/browser/media/index.ts", "src/templates/assets/javascripts/browser/request/index.ts", "src/templates/assets/javascripts/browser/viewport/offset/index.ts", "src/templates/assets/javascripts/browser/viewport/size/index.ts", "src/templates/assets/javascripts/browser/viewport/_/index.ts", "src/templates/assets/javascripts/browser/viewport/at/index.ts", "src/templates/assets/javascripts/browser/worker/index.ts", "src/templates/assets/javascripts/_/index.ts", "src/templates/assets/javascripts/components/_/index.ts", "src/templates/assets/javascripts/components/announce/index.ts", "src/templates/assets/javascripts/components/consent/index.ts", "src/templates/assets/javascripts/templates/tooltip/index.tsx", "src/templates/assets/javascripts/templates/annotation/index.tsx", "src/templates/assets/javascripts/templates/clipboard/index.tsx", "src/templates/assets/javascripts/templates/search/index.tsx", "src/templates/assets/javascripts/templates/source/index.tsx", "src/templates/assets/javascripts/templates/tabbed/index.tsx", "src/templates/assets/javascripts/templates/table/index.tsx", "src/templates/assets/javascripts/templates/version/index.tsx", "src/templates/assets/javascripts/components/tooltip2/index.ts", "src/templates/assets/javascripts/components/content/annotation/_/index.ts", "src/templates/assets/javascripts/components/content/annotation/list/index.ts", "src/templates/assets/javascripts/components/content/annotation/block/index.ts", "src/templates/assets/javascripts/components/content/code/_/index.ts", "src/templates/assets/javascripts/components/content/details/index.ts", "src/templates/assets/javascripts/components/content/mermaid/index.css", "src/templates/assets/javascripts/components/content/mermaid/index.ts", "src/templates/assets/javascripts/components/content/table/index.ts", "src/templates/assets/javascripts/components/content/tabs/index.ts", "src/templates/assets/javascripts/components/content/_/index.ts", "src/templates/assets/javascripts/components/dialog/index.ts", "src/templates/assets/javascripts/components/tooltip/index.ts", "src/templates/assets/javascripts/components/header/_/index.ts", "src/templates/assets/javascripts/components/header/title/index.ts", "src/templates/assets/javascripts/components/main/index.ts", "src/templates/assets/javascripts/components/palette/index.ts", "src/templates/assets/javascripts/components/progress/index.ts", "src/templates/assets/javascripts/integrations/clipboard/index.ts", "src/templates/assets/javascripts/integrations/sitemap/index.ts", "src/templates/assets/javascripts/integrations/instant/index.ts", "src/templates/assets/javascripts/integrations/search/highlighter/index.ts", "src/templates/assets/javascripts/integrations/search/worker/message/index.ts", "src/templates/assets/javascripts/integrations/search/worker/_/index.ts", "src/templates/assets/javascripts/integrations/version/index.ts", "src/templates/assets/javascripts/components/search/query/index.ts", "src/templates/assets/javascripts/components/search/result/index.ts", "src/templates/assets/javascripts/components/search/share/index.ts", "src/templates/assets/javascripts/components/search/suggest/index.ts", "src/templates/assets/javascripts/components/search/_/index.ts", "src/templates/assets/javascripts/components/search/highlight/index.ts", "src/templates/assets/javascripts/components/sidebar/index.ts", "src/templates/assets/javascripts/components/source/facts/github/index.ts", "src/templates/assets/javascripts/components/source/facts/gitlab/index.ts", "src/templates/assets/javascripts/components/source/facts/_/index.ts", "src/templates/assets/javascripts/components/source/_/index.ts", "src/templates/assets/javascripts/components/tabs/index.ts", "src/templates/assets/javascripts/components/toc/index.ts", "src/templates/assets/javascripts/components/top/index.ts", "src/templates/assets/javascripts/patches/ellipsis/index.ts", "src/templates/assets/javascripts/patches/indeterminate/index.ts", "src/templates/assets/javascripts/patches/scrollfix/index.ts", "src/templates/assets/javascripts/patches/scrolllock/index.ts", "src/templates/assets/javascripts/polyfills/index.ts"], + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*\n * Copyright (c) 2016-2024 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getActiveElement,\n getOptionalElement,\n requestJSON,\n setLocation,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchScript,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountProgress,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantNavigation,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchEllipsis,\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Functions - @todo refactor\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @returns Search index observable\n */\nfunction fetchSearchIndex(): Observable {\n if (location.protocol === \"file:\") {\n return watchScript(\n `${new URL(\"search/search_index.js\", config.base)}`\n )\n .pipe(\n // @ts-ignore - @todo fix typings\n map(() => __index),\n shareReplay(1)\n )\n } else {\n return requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget(location$)\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? fetchSearchIndex()\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up progress indicator */\nconst progress$ = new Subject()\n\n/* Set up instant navigation, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantNavigation({ location$, viewport$, progress$ })\n .subscribe(document$)\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"link[rel=prev]\")\n if (typeof prev !== \"undefined\")\n setLocation(prev)\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"link[rel=next]\")\n if (typeof next !== \"undefined\")\n setLocation(next)\n break\n\n /* Expand navigation, see https://bit.ly/3ZjG5io */\n case \"Enter\":\n const active = getActiveElement()\n if (active instanceof HTMLLabelElement)\n active.click()\n }\n })\n\n/* Set up patches */\npatchEllipsis({ viewport$, document$ })\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Progress bar */\n ...getComponentElements(\"progress\")\n .map(el => mountProgress(el, { progress$ })),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, {\n viewport$, header$, main$, target$\n })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.progress$ = progress$ /* Progress indicator subject */\nwindow.component$ = component$ /* Component observable */\n", "/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n};\n", "/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n", "/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n", "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n *\n * @class Subscription\n */\nexport class Subscription implements SubscriptionLike {\n /** @nocollapse */\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n * @return {void}\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n", "import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification, subscriber: Subscriber) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n", "import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n", "/* tslint:disable:no-empty */\nexport function noop() { }\n", "import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification(value: T) {\n return createNotification('N', value, undefined) as NextNotification;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n", "import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n *\n * @class Subscriber\n */\nexport class Subscriber extends Subscription implements Observer {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @nocollapse\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber | Observer; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber | Observer) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param {T} [value] The `next` value.\n * @return {void}\n */\n next(value?: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param {any} [err] The `error` exception.\n * @return {void}\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n * @return {void}\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver implements Observer {\n constructor(private partialObserver: Partial>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber extends Subscriber {\n constructor(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as (((value: T) => void) | undefined),\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent\n * @param subscriber The stopped subscriber\n */\nfunction handleStoppedNotification(notification: ObservableNotification, subscriber: Subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n", "/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n", "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity(x: T): T {\n return x;\n}\n", "import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe(fn1: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction, fn3: UnaryFunction): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction,\n ...fns: UnaryFunction[]\n): UnaryFunction;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array>): UnaryFunction {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray(fns: Array>): UnaryFunction {\n if (fns.length === 0) {\n return identity as UnaryFunction;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction) => fn(prev), input as any);\n };\n}\n", "import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n *\n * @class Observable\n */\nexport class Observable implements Subscribable {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator | undefined;\n\n /**\n * @constructor\n * @param {Function} subscribe the function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable, subscriber: Subscriber) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @owner Observable\n * @method create\n * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor\n * @return {Observable} a new observable\n * @nocollapse\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = (subscribe?: (subscriber: Subscriber) => TeardownLogic) => {\n return new Observable(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @method lift\n * @param operator the operator defining the operation to take on the observable\n * @return a new observable with the Operator applied\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift(operator?: Operator): Observable {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * Use it when you have all these Observables, but still nothing is happening.\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,\n * or the first of three possible handlers, which is the handler for each value emitted from the subscribed\n * Observable.\n * @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.\n * @return {Subscription} a subscription reference to the registered handlers\n * @method subscribe\n */\n subscribe(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next a handler for each value emitted by the observable\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n */\n forEach(next: (value: T) => void): Promise;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n const subscriber = new SafeSubscriber({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @method Symbol.observable\n * @return {Observable} this instance of the observable\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable;\n pipe(op1: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction,\n ...operations: OperatorFunction[]\n ): Observable;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n * @method pipe\n * @return {Observable} the Observable result of all of the operators having\n * been called in the order they were passed in.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n */\n pipe(...operations: OperatorFunction[]): Observable {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @method toPromise\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver(value: any): value is Observer {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber(value: any): value is Subscriber {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n", "import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate(\n init: (liftedSource: Observable, subscriber: Subscriber) => (() => void) | void\n): OperatorFunction {\n return (source: Observable) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber, liftedSource: Observable) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n", "import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber extends Subscriber {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n", "import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n", "import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject extends Observable implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @nocollapse\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = (destination: Observer, source: Observable): AnonymousSubject => {\n return new AnonymousSubject(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift(operator: Operator): Observable {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return {Observable} Observable that the Subject casts to\n */\n asObservable(): Observable {\n const observable: any = new Observable();\n observable.source = this;\n return observable;\n }\n}\n\n/**\n * @class AnonymousSubject\n */\nexport class AnonymousSubject extends Subject {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer,\n source?: Observable\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n", "import { Subject } from './Subject';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n *\n * @class BehaviorSubject\n */\nexport class BehaviorSubject extends Subject {\n constructor(private _value: T) {\n super();\n }\n\n get value(): T {\n return this.getValue();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n\n getValue(): T {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n\n next(value: T): void {\n super.next((this._value = value));\n }\n}\n", "import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n", "import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject extends Subject {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param bufferSize The size of the buffer to replay on subscription\n * @param windowTime The amount of time the buffered items will stay buffered\n * @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n *\n * @class Action\n */\nexport class Action extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler.\n * @return {void}\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n", "import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction extends Action {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n * @return {any}\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n", "import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @class Scheduler\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return {number} A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param {function(state: ?T): ?Subscription} work A function representing a\n * task, or some unit of work to be executed by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler itself.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @return {Subscription} A subscription in order to be able to unsubscribe\n * the scheduled work.\n */\n public schedule(work: (this: SchedulerAction, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @type {boolean}\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @type {any}\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * Schedule task as if you used setTimeout(task, duration)\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { Subscription } from '../Subscription';\nimport { QueueScheduler } from './QueueScheduler';\nimport { SchedulerAction } from '../types';\nimport { TimerHandle } from './timerHandle';\n\nexport class QueueAction extends AsyncAction {\n constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (delay > 0) {\n return super.schedule(state, delay);\n }\n this.delay = delay;\n this.state = state;\n this.scheduler.flush(this);\n return this;\n }\n\n public execute(state: T, delay: number): any {\n return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n }\n\n protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n\n // Otherwise flush the scheduler starting with this action.\n scheduler.flush(this);\n\n // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n // `TimerHandle`, and generally the return value here isn't really used. So the\n // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n // as opposed to refactoring every other instanceo of `requestAsyncId`.\n return 0;\n }\n}\n", "import { AsyncScheduler } from './AsyncScheduler';\n\nexport class QueueScheduler extends AsyncScheduler {\n}\n", "import { QueueAction } from './QueueAction';\nimport { QueueScheduler } from './QueueScheduler';\n\n/**\n *\n * Queue Scheduler\n *\n * Put every next task on a queue, instead of executing it immediately\n *\n * `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queue` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n * queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n * console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n * if (state !== 0) {\n * console.log('before', state);\n * this.schedule(state - 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * console.log('after', state);\n * }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n\n/**\n * @deprecated Renamed to {@link queueScheduler}. Will be removed in v8.\n */\nexport const queue = queueScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction extends AsyncAction {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * Perform task when `window.requestAnimationFrame` would fire\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html:
\n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n", "import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * Just emits 'complete', and nothing else.\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n", "export const isArrayLike = ((x: any): x is ArrayLike => x && typeof x.length === 'number' && typeof x !== 'function');", "import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike {\n return isFunction(value?.then);\n}\n", "import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable {\n return isFunction(input[Symbol_observable]);\n}\n", "import { isFunction } from './isFunction';\n\nexport function isAsyncIterable(obj: any): obj is AsyncIterable {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n", "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n", "export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n", "import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable {\n return isFunction(input?.[Symbol_iterator]);\n}\n", "import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator(readableStream: ReadableStreamLike): AsyncGenerator {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike(obj: any): obj is ReadableStreamLike {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an + +
+

Histórico de Revisão

+ + + + + + + + + + + + + + + + + + + + + + + + + +
DataDescriçãoAutor
30/07/2024Criação documentoÁlvaro Gouvea
30/07/2024Correção de ValorÁlvaro Gouvea
06/08/2024Correção do DocumentoÁlvaro Gouvea
+

Referências

+

Custo de um aluno para a Universidade Federal, último acesso em 30/07/2024

+

Notebook Lenovo, último acesso em 30/07/2024

+

Energia elétrica: Estimado conforme amostra da companhia de energia (NeoEnergia), último acesso em 30/07/2024

+

Calculadora de Inflação Banco Central, último acesso em 06/08/2024

+

Custos com internet, último acesso em 30/07/2024

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/eap/index.html b/gestao/eap/index.html new file mode 100644 index 0000000..f2d91c5 --- /dev/null +++ b/gestao/eap/index.html @@ -0,0 +1,2267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + EAP - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Estrutura Analítica do Projeto

+

A Estrutura Analítica do Projeto (EAP) é uma representação hierárquica que divide o escopo do projeto em partes menores e mais gerenciáveis. A EAP fornece uma visão clara e detalhada das entregas e das fases do projeto, facilitando o planejamento, a execução e o controle do projeto. A imagem abaixo descreve a EAP deste projeto, destacando suas principais entregas e componentes.

+ + +

No primeiro nível tem-se o projeto, seguido pelo nível que representa as fases do projeto (Iniciação, Planejamento, Execução e Encerramento), que tenta dar uma noção de tempo e andamento do projeto ao longo do período definido. No nível abaixo, tem-se os pacotes de trabalho, ou seja, as entregas de cada fase, as quais são especificadas em tarefas, representadas pelos quadros em azul.

+

Histórico de Versão

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento28/07/24Sara Campos
Atualização03/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/evm/index.html b/gestao/evm/index.html new file mode 100644 index 0000000..4672ff4 --- /dev/null +++ b/gestao/evm/index.html @@ -0,0 +1,2422 @@ + + + + + + + + + + + + + + + + + + + + + + + + + EVM - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

EVM - Earned Value Management

+

O EVM (Earned Value Management) é uma metodologia de gerenciamento de projetos que integra cronograma, custos e escopo para monitorar o desempenho do projeto. A partir de dados planejados e reais, o EVM permite criar expectativas de resultados futuros e ajustar o andamento conforme necessário. Dentro do EVM, uma ferramenta fundamental é a Análise de Valor Agregado (EVA), uma técnica quantitativa que avalia o desempenho do projeto ao calcular as variações no cronograma e nos custos.

+

Quando 20% do projeto está concluído, o desempenho atual pode ser usado para prever o futuro do projeto com uma margem de erro de aproximadamente 10%. Essa capacidade preditiva torna o EVM uma das mais eficazes ferramentas de controle de custos em projetos.

+

Caso exista maior interesse sobre a metodologia Agile EVM, o material referente à ela pode ser encontrado no seguinte artigo: AgileEVM – Earned Value Management in Scrum Projects. Foi utilizada como base a tabela feita pelo grupo Ada.

+

EVM - Sentinela

+

O processo de monitoramento do projeto se iniciou junto à primeira sprint de desenvolvimento, a Spritn 1. Com os custos do projto já relatados no documento de Custos.

+

O acesso à planilha incluindo a tabela e referentes g´raficos pode ser encontrado aqui.

+ + +

Análise das Major Releases

+

Baseando-se nos gráficos gerados por sprint com suas referências de Valor Agregado x Valor Planejado é possível tirar conclusões sobre cada uma das major releases entregue pela equipe.

+

Release 1

+

r1

+

A Release 1 contou com duas semanas totais de desenvolvimento, com um planejamento do valor agregado do sistema próximo à 25% do total esperado. Porém por dificuldades iniciais da equipe no processo de desenvolvimento o valor total entregue e aceito não alcançou essa meta.

+

MVP

+

mvp

+

A entrega da Release MVP consistiu em 4 semanas completas de desenvolvimento. Como pode ser verificado pelo gráfico, as primeiras semanas de desenvolvimento não trouxeram nenhum valor agregado enquanto o valor planejado continuava crescendo. Quanto ao valor planejado, esse cescimento constante se dava pela utilização de metodologias ágeis por parte da equipe que se baseiam na entrega contínua de valor. Já o comportamento do valor agregado pode ser relacionado com tanto a necessidade de reescrita e organização de critérios de aceitação e histórias de usuário, quanto à demora por parte do cliente para validação das histórias entregues.

+

Release N

+

rn

+

Para a entrega final, o projeto contou com 2 sprints de desenvolvimento. O foco dessas sprints era finalizar as histórias de usuário similarmente à conrrigir possíveis erros de funcionalidade ou compreensão de histórias de usuário anteriores, de forma que o planejamento dessas sprints trouxe menor quantidade de pontos por sprint. Porém por conta de avanço na aceitação por parte do usuário tivemos maior quantidade de pontos de história fechados.

+

Análise Total

+

total +Assim, analisando o gráfico total do projeto é possível ver uma estagnação da equipe para finalizar as entregas, muito passando pelos problemas citados de erros de comunicação levando à reescrita de histórias e critérios de aceitação, assim como a demora muitas vezes para validas as entregas já relizadas. Ainda assim, foi possível finalizar muitas das histórias do projeto.

+

Histórico de Revisão

+ + + + + + + + + + + + + + + +
DataDescriçãoAutor
08/09/2024Criação do DocumentoÁlvaro Gouvea
+

Referências

+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/guia-de-contribuicao/index.html b/gestao/guia-de-contribuicao/index.html new file mode 100644 index 0000000..4d15b76 --- /dev/null +++ b/gestao/guia-de-contribuicao/index.html @@ -0,0 +1,2595 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Guia de contribuição - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Guia de Contribuição

+

Este é o guia de contribuição para o projeto 2024.1-SENTINELA. Antes de iniciar qualquer desenvolvimento que contribua para esse projeto, ler esse documento é essencial para o entendimento das regras.

+

As contribuições podem ser iniciadas a partir das issues já definidas.

+

Como contribuir

+

Índice:

+
    +
  1. Como criar uma issue
  2. +
  3. Como criar sua branch
  4. +
  5. Regras de commits
  6. +
  7. Regras de um PR
  8. +
+

Politica de issues

+

As issues devem ser criadas no repositório de documentação do projeto.

+

As issues do projetos devem ser completas e explicativas, seguindo o template de issue do repositório.

+

As issues devem conter:

+
    +
  • Um título conciso e descritivo;
  • +
  • Uma descrição que deve incluir uma descrição completa da issue e suas tarefas;
  • +
  • Em caso de História de Usuário, descrever de maneira clara e detalhadas os criterios de aceitação, assim como adicionar o prótitpo navegável do fluxo em questão;
  • +
  • Ao menos um Assignee responsável pela issue;
  • +
  • Labels;
  • +
  • Milestone (sprint) em que a issue espera ser concluiída;
  • +
  • Estimated (pontuação) atribuida a issue;
  • +
+

Labels

+

Na criação de uma issue, devem ser usados os rótulos abaixo para classifcá-la:

+
    +
  • Bug: indica um problema ou comportamento inesperados
  • +
  • UX: indica que a issue é referente a práticas de User Experience
  • +
  • Treinamento: indica que a issue é sobre treinamentos (dojos)
  • +
  • Hotfix (cor #d73a4a): indica uma correção de defeitos críticos
  • +
  • Docs (cor #0075ca): indica a aplicação de melhorias ou adições à documentação do projeto
  • +
  • Feature (cor #094EF2): indica a introdução de uma funcionalidade nova US (cor #BE71F6): indica que a issue é uma história de usuário (user story)
  • +
  • Frontend (cor #56384A): Indica que está relacionada ao frontend da aplicação
  • +
  • Backend (cor #95BDC7): Indica que está relacionada ao backend da aplicação
  • +
  • Arq (cor #0D5571): indica mudanças na arquitetura da aplicação ou de um de seus módulos ou serviços
  • +
  • Devops (cor #9014A0): indica mudanças na esteira de integração e disponibilização contínua
  • +
  • Analytics (cor #12477F): indica mudanças nos analisadores estáticos
  • +
  • Easy (cor #C5DEF5): indica que a issue tem uma dificuldade baixa
  • +
  • Medium (cor #BFD4F2): indica que a issue possui um grau médio de dificuldade
  • +
  • Hard (cor #D4C5F9): indica que a issue possui um alto grau de dificuldade
  • +
  • EPS #006633: indica que a issue será trabalhado por alunos da disciplina de Engenharia de Produto de Software (EPS)
  • +
  • MDS (cor #0068b4): indica que a issue será trabalhado por alunos da disciplina de Métodos de Desenvolvimento de Software (MDS)
  • +
+

Politica de branches

+

Repositórios de desenvolvimento

+

Nos repositórios a devel é a branch padrão que está sempre atualizada. A branch main comporta as Releases lançadas do projeto, sendo a branch mais estável.

+

main

+

A branch main deve ser a branch mais estável do projeto, que estará em produção. Essa branch é protegida de commits e para o desenvolvimento de novas funcionalidades, deve receber Pull Requests (PRs).

+

development

+

A branch devel deve ser a branch de desenvolvomento do projeto, que estará em produção. Essa branch também é protegida de commits e para o desenvolvimento de novas funcionalidades, deve receber Pull Requests assim como a main(PRs). Uma vez que todas as funcionalidades da sprint são testadas e mescladas na branch de desenvolvimento podemos mesclar com a branch principal, a main.

+

Novas branches

+

As branches para o desenvolvimento de novas features devem ser criadas a partir da branch devel e devem seguir o padrão x-nome-da-issue, onde x é o número da issue que será resolvida na branch, acompanhado pelo nome da issue.

+

Os Pull Requests das novas branches devem ser feitos para a branch devel.

+

Repositório de documentação

+

No repositório de documentação temos as branches main e gh-pages. Onde na main está o código da página de documentação do github pages e na branch gh-pages está o site compilado e em produção.

+

Assim como nos repositórios de desenvolvimento do projeto, no repositório de documentação a branch main está protegida e só deve aceitar modificações por Pull Requests..

+

As novas branches, assim como nos repositórios de desenvolvimento devem seguir a estrutura x-nome-da-issue.

+

Politica de commits

+

Os commits durante o desenvolvimento do código devem frequentes, descritivos e concisos.

+

Os commits devem ser feitos em inglês utilizando os verbos no imperativo.

+

Os commits podem ser feitos utilizando o parametro -s para ter a assinatura do autor do commit. Caso o commit tenha sido feito em pareamento, deve constar no commit os co-autores.

+

O commit deve começar com [y:x] -, sendo x o número da issue que está sendo desenvolvida. e y a categoria do commit (feat, fix, hotfix, ...)

+

Exemplos de commit:

+
git commit -sm "[feat:7] - Add contributing guide
+
+Co-authored-by: Nome da dupla <emaildadupla@email.com>"
+
+git commit -sm "[fix:7] - Add contributing guide
+
+Co-authored-by: Nome da dupla <emaildadupla@email.com>"
+
+git commit -sm "[docs:7] - Add contributing guide
+
+

Politica de pull requests

+

Os PRs devem ser feitos a branch devel.

+

Os Pull Requests devem ser feitos seguindo o template:

+
**Issue:** closes #X (sendo #x o link para a issue x)
+
+## Descrição
+Descrição completa do que foi feito
+
+
+

Onde só deve ser utilizado o closes antes do link da issue, caso o PR resolva completamente a issue citada.

+

Caso o PR seja feito em um dos repositórios de desenvolvimento (backend de x, forntend,...), o link para a issue do repositório de documentação é feito da seguinte forma: fga-eps-mds/2024.1-SENTINELA-DOC#x, onde x é o número da issue. E no lugar de closes deve ser utilizado resolves.

+

Em casos de PRs em que ainda estão sendo desenvolvidos, deve ser acrescentado a sigla WIP antes do título do PR.

+

Os PRs devem conter:

+
    +
  • Um título conciso e descritivo;
  • +
  • Um Assignee responsável pelo PR;
  • +
  • Um Reviewer responsável pela revisão do PR;
  • +
  • Labels significativas;
  • +
  • Uma issue associada;
  • +
  • Uma descrição, seguindo o template do repositório, que deve incluir uma descrição completa do que foi feito e a issue relacionada.
  • +
+

Os PRs só serão aceitos após passarem pelo CI estabelecido e por duas revisões.

+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documentoVictor Yukio
AtualizaçãoIngrid
Revisão e adição das labels03/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/manual-de-instalacao/index.html b/gestao/manual-de-instalacao/index.html new file mode 100644 index 0000000..4c23a06 --- /dev/null +++ b/gestao/manual-de-instalacao/index.html @@ -0,0 +1,2627 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Manual de instalação - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Manual de Instalação do Projeto

+

Visão Geral

+

Este projeto utiliza uma arquitetura de microserviços, composta por quatro repositórios:

+
    +
  1. Frontend: Interface do usuário.
  2. +
  3. Backend - Usuários: Serviço responsável pelo gerenciamento de usuários.
  4. +
  5. Backend - Financeiro: Serviço responsável pelas operações financeiras.
  6. +
  7. Backend - Benefícios: Serviço responsável pela gestão de benefícios.
  8. +
+

Todos os repositórios são dockerizados, garantindo que os serviços possam ser facilmente configurados e executados.

+

Pré-requisitos

+

Antes de iniciar o processo de instalação, certifique-se de que os seguintes softwares estejam instalados:

+ +

Estrutura de Repositórios

+ +
+

Passo a Passo de Instalação

+

1. Clonar os Repositórios

+

Clone os repositórios do projeto em suas respectivas pastas.

+
# Clonar o frontend
+$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-FRONT
+
+# Clonar o backend de usuários
+$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-BACKEND-USUARIOS
+
+# Clonar o backend de financeiro
+$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-BACKEND-FINANCEIRO
+
+# Clonar o backend de benefícios
+$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-BACKEND-BENEFICIOS
+
+
+

2. Configurar Variáveis de Ambiente

+

Para cada serviço, crie ou edite o arquivo .env na raiz de cada repositório com as variáveis de ambiente necessárias. Aqui está um exemplo geral para cada serviço:

+
# Exemplo de .env
+DB_HOST=db  # Endereço do banco de dados
+DB_PORT=5432  # Porta do banco de dados
+DB_USER=user  # Usuário do banco de dados
+DB_PASSWORD=senha  # Senha do banco de dados
+DB_NAME=nome_do_banco  # Nome do banco de dados
+PORT=3000  # Porta que o serviço vai rodar
+
+

Certifique-se de que as variáveis estejam corretamente configuradas em cada microserviço.

+

3. Subir os Containers com Docker

+

Navegue até a pasta de cada serviço e execute os comandos abaixo para rodar os containers com Docker. Abaixo está o passo a passo para cada serviço:

+

3.1 Frontend

+

Entre na pasta do frontend e execute os seguintes comandos:

+
$ cd frontend
+$ docker build nome-da-imagem
+$ docker run --name nome-do-container -p 5173:5173 nome-da-imagem
+
+
+

O frontend estará disponível em: http://localhost:5173 (ou a porta especificada no .env).

+

3.2 Backend - Usuários

+

Entre na pasta do backend de usuários e execute:

+
$ cd backend-usuarios
+$ docker-compose up --build
+
+

Este serviço estará disponível na porta configurada no .env, como http://localhost:3001.

+

3.3 Backend - Financeiro

+

Entre na pasta do backend financeiro e execute:

+
$ cd backend-financeiro
+$ docker-compose up --build
+
+

Este serviço estará disponível na porta configurada no .env, como http://localhost:3002.

+

3.4 Backend - Benefícios

+

Entre na pasta do backend de benefícios e execute:

+
$ cd backend-beneficios
+$ docker-compose up --build
+
+

Este serviço estará disponível na porta configurada no .env, como http://localhost:3003.

+

Monitoramento dos Containers

+

Você pode verificar o status de todos os containers em execução utilizando o comando:

+
$ docker ps
+
+

Caso queira parar todos os serviços, navegue até cada repositório e execute:

+
$ docker-compose down --volumes
+
+

Para remover containers que não estão mais em execução criados pelos docker-compose:

+
$ docker-compose rm -f
+
+

Considerações Finais

+

Com os containers configurados e em execução, a aplicação completa estará disponível para uso. Certifique-se de que todas as portas configuradas estejam livres e que as dependências de rede entre os microserviços estejam funcionando corretamente (como a comunicação entre backends e o banco de dados). Para quaisquer problemas, consulte os logs dos containers com o comando:

+
docker logs <nome_do_container>
+
+

Caso precise recriar os containers, sempre utilize o parâmetro --build ao rodar o docker-compose para garantir que a imagem seja recompilada.

+
docker-compose up --build
+
+

Histórico de Versões

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Ingrid Carvalho
Revisão08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/melhorias-defeitos/index.html b/gestao/melhorias-defeitos/index.html new file mode 100644 index 0000000..caefac0 --- /dev/null +++ b/gestao/melhorias-defeitos/index.html @@ -0,0 +1,2355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Melhorias e defeitos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Melhorias e defeitos identificados no projeto

+

Ao longo do desenvolvimento, foram identificadas evoluções corretivas e adaptativas, bem como bugs de funcionamento, todos apresentados neste documento.

+

A qualidade de entrega sempre foi considerada como essencial para o time, de forma que, sempre que algum integrante identificava alguma oportunidade de adaptação ou correção no produto, antes ou depois da aceitação por parte dos P.Os, o encaminhamento era feito.

+

Assim, foram adicionadas issues de Enhancement relacionadas às US que apresentavam essa necessidade. No total, foram instanciadas três melhorias, das quais duas foram conduzidas e entregues aos P.Os.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ENHUSDescriçãoEntrega
#105US02Evolução adaptativa da US02 (Solicitar filiação), que implica na necessidade dos campos Sexo, Lotação, Órgão e Situação Atual se tornarem obrigatórios e os campos Órgão e Lotação devem se tornam campos do tipo Dropdown.Entregue
#108US05Evolução corretiva que apresente feedback para o usuário ao alterar o nome de conta bancária para string vaziaEntregue
#106US04Ajuste do banco de dados, de forma que, a tabela de sindicalizados seja filha da tabela usuários (herança) e reflexo disso no frontend, ou seja, exibição dos dados na tela conforme tipo de usuário.Não finalizada
+

Além disso, foi instanciada a necessidade de duas novas US no Backlog do Produto, das quais uma foi trazida para desenvolvimento nesse semestre, devido a sua prioridade (US35 - Cadastrar órgãos/lotações), e a outra foi identificada para ser desenvolvida futuramente, em outros semestres (US36 - Cadastrar postos de trabalho).

+

A não finalização da US04, assim como a não entrega da ENH-US04 implicam na necessidade de revisão e refatoramento dos formulários referentes a filiação e cadastro de usuários do tipo filiado, o que deve ser conduzido futuramente pelos próximos times responsáveis.

+

Com relação a defeitos, alguns foram identificados ao longo do projeto conforme retorno do usuário nos testes de aceitação. Todos estes pedidos foram encaminhados para correção e entregues de acordo, permitindo assim a entrega final das US.

+

Nas semanas finais (Release N), quando o foco era na entrega de melhorias e correções, o time criou um Mapeamento de Bugs a serem corrigidos, bem como foram inspecionados minuciosamente os estilos (CSS/HTML) de algumas páginas para garantir uma boa Experiência de Usuário. Foram elas:

+
    +
  • contributionHistoric [feito]
  • +
  • fornecedores (create and update) [feito]
  • +
  • list roles page [feito]
  • +
  • list user [feito]
  • +
  • profile (update) [feito]
  • +
+

Por fim, o projeto é finalizado com a necessidade das seguintes correções de defeitos:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
USDefeitoDescriçãoPrioridade
US04Inicialmente, havia sido levantado que as telas de cadastro de usuários teriam os dados pedidos pelos P.Os. No entanto, enquanto era desenvolvida, notou-se que essa US precisava de telas para representar usuários do tipo filiados. Essa correção, no entanto, não foi finalizada a nível de interface.A correção foi feita apenas a nível de banco de dados, já que agora as tabelas Usuário e Filiado possuem relação de herança, mas é preciso criar protótipos de como essas telas irão funcionar com a mudança e refletir isso no frontend.A prioridade dessa correção é considerada alta, pois afeta a performance de outras US e é uma funcionalidade básica do sistema.
US34Quando uma solicitação é rejeitada, um email deve ser enviado ao solicitante para que ele seja informado sobre a rejeição e, caso queira, entre em contato com o sindicatoEsse defeito deve ser corrigido com uma revisão simples do código, visto que, a funcionalidade foi implementada e já havia sido testada antes, mas no momento do teste de aceitação final do usuário acabou não funcionando perfeitamenteA prioridade dessa correção não é tão alta por não afetar outras US, mas por ser uma correção rápida pode ser significativamente priorizada.
US20Campo de data com formato MM/DD/YYYYCadastros antigos feitos antes de uma correção em relação a data ainda exibem formato MM/DD/YY, ao contrário de DD/MM/YYYY, como era esperado, apesar deste problema não ser mais gerável pelos cadastros do usuárioBaixa prioridade, não afeta outras US
US20Campo de Conta Origem/Destino não recebe contas bancárias cadastradasQuando selecionada a opção de Conta do Sindicato, as contas bancárias que aparecem como opção de preenchimento são estáticasPrioridade alta, porém de baixa complexidade, já que basta uma correção, implementando a requisição GET de Contas Bancárias registradas no sistema
US21Desfazer selção de filtroÉ possível limpar todos os filtros, no entanto, o P.O fez a sugestão de implementar a limpar um filtro por vezPrioridade a ser avaliada pelo P.O
+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
Atualização a partir do feedback do P.O (Adiciona tabela de Defeitos)09/09/24Sara Campos
Atualização a partir do feedback do P.O (Adiciona tabela de Defeitos)14/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/metodologia/index.html b/gestao/metodologia/index.html new file mode 100644 index 0000000..70c9e54 --- /dev/null +++ b/gestao/metodologia/index.html @@ -0,0 +1,2801 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Metodologia - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Metodologia de Trabalho da Equipe

+

Introdução

+

Para as fases inicias do projeto, foi adotada a metodologia de Lean Inception, que foi abordada em mais detalhes na aba homônima, iniciada no Dia 1.

+

Nossa equipe adotou uma metodologia de desevolvimento híbrida baseada em Scrum e práticas do Extreme Programming (XP), Kanban e PMBOK para garantir um desenvolvimento ágil e eficiente. Este documento detalha os processos e ferramentas que utilizamos para organizar e comunicar nosso trabalho.

+

Framework Scrum

+

1. Sprints

+
    +
  • O Scrum traz uma abordagem que ocorre ao longo sprints, que são esses períodos de tempo (geralmente uma semana), dentro dos quais são planejadas metas de trabalho a serem realizados.
  • +
+

2. Planning

+
    +
  • Objetivo: Definir as metas e tarefas para o próximo ciclo de desenvolvimento.
  • +
  • Frequência: Toda segunda 21h após reunião com cliente
  • +
  • Participantes: Toda a equipe
  • +
  • Atividades:
  • +
  • Revisar o backlog de produto
  • +
  • Estimar as tarefas utilizando métodos como Planning Poker
  • +
  • Definir as prioridades e selecionar as tarefas para o sprint
  • +
+

3. Standup meeting

+
    +
  • Objetivo: Alinhar o progresso e identificar impedimentos.
  • +
  • Frequência: Terças e quintas entre aulas
  • +
  • Participantes: Toda a equipe
  • +
  • Atividades:
  • +
  • Novas atividades podem ser repassadas
  • +
  • Cada membro responde às perguntas:
      +
    • O que estou fazendo?
    • +
    • Há algum impedimento no meu caminho?
    • +
    +
  • +
+

4. Review

+
    +
  • Objetivo: Apresentar o trabalho realizado durante a sprint e validar com o PO.
  • +
  • Frequência: Toda segunda 20h em reunião com cliente
  • +
  • Participantes: Toda a equipe, incluindo stakeholders
  • +
  • Atividades:
  • +
  • Demonstração das funcionalidades desenvolvidas
  • +
  • Feedback dos stakeholders
  • +
  • Atualização do backlog com base no feedback recebido
  • +
+

5. Retrospectiva

+
    +
  • Objetivo: Refletir sobre o sprint passado e identificar melhorias para os próximos sprints.
  • +
  • Frequência: Toda sexta-feira às 16h
  • +
  • Participantes: Toda a equipe
  • +
  • Atividades:
  • +
  • Discussão sobre o que funcionou bem e o que pode ser melhorado
  • +
  • Definição de ações para melhorias contínuas
  • +
+

6. Papéis

+
    +
  • O Scrum sugere os papéis de Product Owner e Scrum Master. Neste trabalho, os representantes do SINDPOL-DF (Matheus Amaral e Davi Mendonça) tiveram uma atuação semelhante a proposta de um Product Owner, representando as necessidades do cliente. Enquanto isso, os estudantes de EPS puderam assumir o papel de Scrum Master, gerenciando, treinando e orientando a Equipe de Desenvolvimento (estudantes de MDS e, em dados momentos, EPS) para cumprir as regras de Scrum e entregar os resultados.
  • +
+

Práticas do Extreme Programming (XP)

+

1. Programação em Pares

+
    +
  • Objetivo: Melhorar a qualidade do código e promover o compartilhamento de conhecimento.
  • +
  • Como funciona: Dois desenvolvedores trabalham juntos no mesmo código, alternando entre os papéis de “Driver” e “Observer”. Neste trabalho, houveram momentos em que a programação envolvia inclusive mais de duas pessoas, em momentos críticos e quando códigos eram debugados. Além disso, o time realizou duas reuniões extraordinárias com a presença de todos integrantes para codar num ambiente em que o grupo como um todo poderia se apoiar e parear conforme necessidade.
  • +
+

2. Integração Contínua (CI/CD)

+
    +
  • Objetivo: Assegurar que o código está sempre em um estado funcional.
  • +
  • Como funciona: O código é integrado e testado automaticamente no SonarQube, permitindo coletar métricas do código rapidamente.
  • +
+

3. Proximidade com o Usuário

+
    +
  • Objetivo: Garantir que o desenvolvimento está alinhado com as necessidades e expectativas do usuário.
  • +
  • Como funciona: Envolvimento constante do usuário final durante o processo de desenvolvimento, com feedback frequente e ajustes conforme necessário.
  • +
+

4. Cadência Rápida de Entregas

+
    +
  • Objetivo: Entregar incrementos de valor ao cliente de forma contínua e rápida.
  • +
  • Como funciona: Entregas frequentes e menores, focando na entrega contínua de valor ao cliente por meio de releases (versões do produto). Com a definição de três releases major no período da disciplina, foram planejadas as entregas de cada uma, de forma que, o trabalho dentro das sprints do Scrum era executado a fim de atingir essas metas.
  • +
+

5. Testes

+
    +
  • Objetivo: Essa prática viabiliza a integração contínua e busca monitorar a qualidade do produto, garantindo que seu comportamento seja condizente com o esperado.
  • +
  • Como funciona: No código fonte são realizados testes unitáios desenvolvidos pela Equipe de Desenvolvimento, enquanto no ambiente de produção são feitos testes de aceitação/testes manuais realizados pelos P.Os e pela Equipe de Desenvolvimento.
  • +
+

Kanban

+

Uso do Quadro Kanban

+
    +
  • Objetivo: Visualizar o fluxo de trabalho e limitar o trabalho em progresso.
  • +
  • Como funciona: As tarefas são movidas através de colunas no quadro, representando diferentes estágios do fluxo de trabalho (Ex.: Backlog, Em Progresso, Em Revisão, Concluído). Foi usado o Zenhub criar essa visualização de progresso das atividades e, ao passo que foi notado gargalo de trabalho em andamento, os Scrum Masters tomaram decisão de não iniciar novas histórias e focar em finalizar entregas de qualidade do que estava In Progress.
  • +
+

PMBOK

+

Gestão de Projetos

+
    +
  • Objetivo: Integrar práticas de gerenciamento de projetos para melhor organização e controle.
  • +
  • Como funciona: Utiliza-se as áreas de conhecimento do PMBOK, como gerenciamento de escopo, tempo, custo e qualidade, adaptando-as ao contexto ágil da equipe. O escopo foi gerenciado pelos Srum Masters com acompanhamento dos P.Os ao longo do semestre, considerando o que havia sido planejado inicialmente e a viabilidade conforme o andamento do trabalho. O custo também foi monitorado por meio de documentos como Custo, com acompanhamento semanal/total do custo, e EVM, com os resultados de Valor Agregado e Valor Planejado. O documento de Riscos demonstra o relato semanal/por sprint dos riscos identificados e seus respectivos graus de probabilidade e impacto, bem como os planejamentos de respostas a cada um deles.
  • +
+

Grupos de processos

+
    +
  • Objetivo: Definir o ciclo de vida do projeto.
  • +
  • Como funciona: Apesar de discordar um pouco da visão ágil nesse sentido, o PMBOK traz um conjunto de fases pelas quais o projeto passa dentro do seu cronograma de execução. Essa visão foi trazida na EAP, onde tem-se os grupos de processos Iniciação, Planejamento, Execução e Encerramento. Essa visão é uma abstração do método, visto que, as atividades nem sempre são resumidas apenas a um grupo de processos, como é a proposta do ágil.
  • +
+

Conclusão

+

Adotando essa combinação de Scrum, XP, Kanban e PMBOK, visamos a maximização da produtividade e a qualidade do nosso produto final. As ferramentas escolhidas suportam nossas necessidades de comunicação e organização, facilitando a colaboração e a transparência em todas as fases do desenvolvimento.

+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documentoVictor Yukio
Revisão18/07/24Sara Campos
Revisão03/08/24Sara Campos
Revisão conforme apontamentos da Release Final14/09/24Sara Campos
+

Referências

+

Scrum: Como fazer mais em menos tempo. Acessado em 14/09/2024. +Práticas em XP: Extreme Programming. Acessado em 14/09/2024.

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/planoQualidade/index.html b/gestao/planoQualidade/index.html new file mode 100644 index 0000000..3a48ce7 --- /dev/null +++ b/gestao/planoQualidade/index.html @@ -0,0 +1,2812 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Qualidade - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Plano de Qualidade

+

Introdução

+

De acordo com a ISO 25010, a qualidade de um produto de software é definida pelo grau em que ele atende aos requisitos de seus usuários, agregando valor. Esses requisitos, que incluem funcionalidade, desempenho, segurança, manutenibilidade, entre outros, são representados no modelo de qualidade, que categoriza a qualidade do produto em características e subcaracterísticas. Para alcançar esses requisitos, é essencial desenvolver e monitorar métricas de forma contínua. O objetivo do planejamento de qualidade é descrever como esse monitoramento foi realizado durante o projeto.

+

Processo de Qualidade

+

Para garantir a qualidade do projeto, integramos cada serviço desenvolvido com a ferramenta SonarQube, utilizando a interface SonarCloud para proporcionar uma análise mais amigável e detalhada de todas as métricas coletadas. O processo é orientado pela validação das US com o cliente, utilizando protótipos e critérios de aceitação, seguido pela implementação contínua de melhorias. Após o desenvolvimento, as funcionalidades passam pelos testes de aceitação conduzidos pelo cliente, assegurando que ajustes e aperfeiçoamentos sejam aplicados. Caso novas melhorias sejam identificadas, elas são incorporadas ao processo de desenvolvimento, reforçando a qualidade do produto.

+

+ eps qualidade +

+ +

Métricas Monitoradas:

+
    +
  • Cobertura de Código
  • +
  • Duplicação de Código
  • +
  • Vulnerabilidades e Bugs
  • +
  • Integração com CI/CD: Configuração do SonarCloud com pipelines de integração contínua.
  • +
  • Alertas e Relatórios: Configuração de thresholds para alertas automáticos e geração de relatórios.
  • +
+

Políticas de Código e Revisão

+
    +
  • Pull Requests e Code Review: Processo de revisão de código e melhores práticas para garantir qualidade.
  • +
  • Padrões de Codificação: Ferramentas e regras aplicadas para padronização do código.
  • +
  • Merge Guidelines: Critérios para fusão de branches e deploy.
  • +
+

Ferramentas de Teste

+

Jest: Framework de testes completo para JavaScript, amplamente usado para testes de unidade, integração e ponta a ponta. Oferece suporte a mocks, snapshots, e uma interface fácil de usar.

+

Vitest: Framework de testes rápido e leve, projetado para o ecossistema JavaScript, com foco em integração com Vite. Suporta mocks, TypeScript e testes ESM, acelerando o desenvolvimento front-end.

+

SonarCloud: plataforma de análise de código que identifica bugs, vulnerabilidades e code smells. Oferece suporte a várias linguagens, integrando-se facilmente ao fluxo CI/CD para garantir a qualidade do código.

+

ZenHub: ferramenta de gerenciamento de projetos que se integra ao GitHub, oferecendo recursos como quadros kanban e relatórios de produtividade

+

Acompanhamento de métricas do sonar

+

Release 1

+

Funcionalidades presentes:

+
    +
  • US01 - Fazer login
  • +
  • US02 - Solicitar filiação
  • +
  • US04 - Cadastrar usuários
  • +
  • US33 - Atualizar dados de usuário
  • +
+

Release 2

+

Funcionalidades presentes:

+
    +
  • US02 - Solicitar filiação (Ajustes pedidos na Release 1)
  • +
  • US19- Cadastrar benefícios
  • +
  • US34 - Gerenciar filiações
  • +
+

Release 3

+

Funcionalidades presentes:

+
    +
  • US03 - Cadastrar fornecedores
  • +
  • US05 - Cadastrar contas bancárias
  • +
  • US17 - Cadastrar perfis no sistema
  • +
+

Release MVP

+

Funcionalidades presentes:

+
    +
  • US01 - Fazer login no sistema (Ajustes pedidos na Release 1)
  • +
  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release 3)
  • +
  • US16 - Visualizar dashboard sobre os sindicalizados
  • +
  • US20 - Cadastrar movimentações financeiras
  • +
  • US23 - Consulta do Histórico de Contribuições do sindicalizado
  • +
  • US35 - Cadastro de órgão/lotação
  • +
  • US34 - Gerenciar solicitações de filiação (Ajustes pedidos na Release 2)
  • +
+

Release 5

+

Funcionalidades presentes:

+
    +
  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release MVP)
  • +
  • US20 - Cadastrar movimentações financeiras (Ajustes pedidos na Release MVP)
  • +
  • US17 - Cadastrar perfis (Ajustes necessários identificados na Release MVP)
  • +
  • US18 - Atribuir perfis
  • +
  • US21 - Gerar relatório de movimentações financeiras
  • +
  • ENH-US02 - Melhorias da US02
  • +
  • ENH-US05 - Melhorias da US05
  • +
+

Modelo de Qualidade do Q-Rapids

+

Foi seguido o modelo de qualidade Q-Rapids. Ele foi projetado para auxiliar equipes de desenvolvimento a tomar decisões informadas com base em métricas de qualidade e dados em tempo real, coletados automaticamente ao longo do ciclo de vida do software. O SonarCloud, plataforma de apoio para monitoramento de métricas de integração contínua, integra diferentes fontes de informação para gerar relatórios e dashboards que oferecem uma visão detalhada sobre a saúde do projeto. Seu objetivo principal é melhorar a qualidade do software, facilitar a gestão de riscos e otimizar processos, permitindo que as equipes sejam mais ágeis e eficazes na entrega de software.

+

Os fatores e métricas de qualidade são critérios usados para avaliar a eficiência, desempenho e confiabilidade de um produto de software, seu processo de desenvolvimento e a organização como um todo. Esses fatores, como manutenibilidade, confiabilidade, usabilidade e eficiência, ajudam a medir quão bem o software atende aos requisitos técnicos e às expectativas dos usuários. As métricas associadas fornecem dados quantitativos que permitem monitorar e melhorar a qualidade continuamente. Utilizá-las é essencial para identificar problemas precocemente, aumentar a satisfação do cliente, reduzir custos com retrabalho e garantir o alinhamento do produto com os objetivos estratégicos da organização.

+

Métricas

+

As métricas definidas para o Sentinela foram:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MétricaDescrição
FilesQuantidade de arquivos de código
FunctionsQuantidade de funções no código
ComplexityComplexidade cognitiva
Comment Lines DensityDensidade (%) de linhas comentadas
Duplicated Lines densityDensidade (%) de linhas duplicadas
CoverageCobertura de código pelos testes
NclocQuantidade de linhas de código
TestsTestes unitários e de integração
Test ErrorsTestes que possuem erros
Test FailuresTestes que falharam
Test Execution TimeTempo de execução dos testes
Security RatingAvaliação de segurança de falhas e vulnerabilidades
+

Métricas para o produto

+

O uso de métricas permite identificar subcaracterísticas associadas e avaliar a qualidade do produto. Essa análise também possibilita medir a produtividade do projeto, gerando resultados que influenciam as decisões de desenvolvimento. Com base nas métricas especificadas no SonarCloud e Q-Rapids, além dos dados coletados, foram definidos os valores mínimos aceitáveis para cada métrica no projeto Sentinela, conforme mostrado nas tabelas abaixo. Os dados referêntes a satisfação do usuário foram coletados a partir do formulário fornecido aos POs, que visa quantificar em escala de 1 a 5 qual o nível de satisfação do cliente quanto ao trabalho realizado e entregue pelo grupo Sentinela 2024/1, baseado nos modelos CSAT e NPS.

+

Repositório do Frontend

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MétricaValor referênciaValor alcançado
Complexityaté 109
Comment Lines Density (%)até 30%1,9%
Duplicated Lines Density (%)até 5%7%
Coverageacima de 80%78,1%
Test Failures00
Test Errors00
Security Rating0 (A)0 (A)
Satisfação do usuárioacima de 35
+

Repositório do Backend - Usuários

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MétricaValor referênciaValor alcançado
Complexityaté 103
Comment Lines Density (%)até 30%4,7%
Duplicated Lines Density (%)até 5%0,0%
Coverageacima de 80%78,2
Test Failures00
Test Errors00
Security Rating0 (A)0 (A)
Satisfação do usuárioacima de 35
+

Repositório do Backend - Financeiro

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MétricaValor referênciaValor alcançado
Complexityaté 101
Comment Lines Density (%)até 30%5,5%
Duplicated Lines Density (%)até 5%0,0%
Coverageacima de 80%86,5%
Test Failures00
Test Errors00
Security Rating0 (A)0 (A)
Satisfação do usuárioacima de 35
+

Repositório do Backend - Benefícios

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MétricaValor referênciaValor alcançado
Complexityaté 102
Comment Lines Density (%)até 30%4,7%
Duplicated Lines Density (%)até 5%0,0%
Coverageacima de 80%78%
Test Failures00
Test Errors00
Security Rating0 (A)1 (E)
Satisfação do usuárioacima de 35
+

Histórico de Versões

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento28/07/24Ingrid Carvalho
Atualizações sobre o sonar31/08/2024Ingrid Carvalho
Atualizações com as métricas08/09/2024Ingrid Carvalho
Revisão08/09/2024Sara Campos
+

Referências

+

ISO/IEC 25010

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/riscos/index.html b/gestao/riscos/index.html new file mode 100644 index 0000000..1325dc1 --- /dev/null +++ b/gestao/riscos/index.html @@ -0,0 +1,2336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Riscos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Riscos do Projeto Sentinela

+

Introdução

+

O projeto Sentinela envolve o desenvolvimento colaborativo de um software e, para garantir seu sucesso, é essencial identificar, avaliar e mitigar os riscos que possam impactar o projeto. A seguir, são descritos os principais riscos mapeados, suas probabilidades e impactos, além das estratégias de monitoramento contínuo. Abaixo pode-se visualizar o Mapeamento de Riscos e Gráfico de Riscos

+ + +

Lista de Riscos do Projeto Sentinela

+

As categorias de riscos no projeto Sentinela são divididas em cinco grupos principais: Organizacional, Técnico, Qualidade, Gerência e Externo. Os riscos organizacionais envolvem desafios relacionados ao comprometimento da equipe, comunicação e motivação, podendo gerar atrasos e conflitos internos. Os técnicos abordam dificuldades com tecnologias, arquitetura, deploy e ambientação, que podem impactar diretamente o desenvolvimento e entrega da aplicação. Já os riscos de qualidade tratam de problemas como ausência de testes, falhas de UX/UI e má prática no processo de desenvolvimento, afetando a experiência do usuário e a adequação do produto aos requisitos. Na categoria de gerência, estão os riscos relacionados à definição de escopo, gestão de tempo, cronograma e pontuação de US, que podem comprometer o andamento eficiente do projeto. Por fim, os riscos externos são imprevistos fora do controle da equipe, como suspensão de aulas, infraestrutura inadequada e afastamento de integrantes, que podem gerar interrupções no progresso do projeto.

+

1. Organizacional

+
    +
  1. Falha de comunicação
  2. +
  3. Descomprometimento da equipe
  4. +
  5. Erro de priorização
  6. +
  7. Desistência de membros
  8. +
  9. Desavenças entre os membros
  10. +
  11. Tensão de fim de semestre
  12. +
  13. Falta de motivação
  14. +
  15. Atraso nas entregas
  16. +
+

2. Técnico

+
    +
  1. Dificuldade em criar backlog
  2. +
  3. Má escolha das tecnologias
  4. +
  5. Dificuldade de ambientação
  6. +
  7. Arquitetura mal definida
  8. +
  9. Dificuldade de deploy da aplicação
  10. +
  11. Dificuldade em hospedar a aplicação
  12. +
  13. Documentação que induz ao erro
  14. +
  15. Dificuldade com as tecnologias
  16. +
+

3. Qualidade

+
    +
  1. Ausência de testes
  2. +
  3. Falhas e bugs
  4. +
  5. Má implementação de UX
  6. +
  7. Má implementação de UI
  8. +
  9. Má prática do processo de desenvolvimento
  10. +
  11. Aplicação não atender expectativas do usuário
  12. +
  13. Não cumprimento dos requisitos elicitados
  14. +
  15. Falta de validação com o stakeholder
  16. +
+

4. Gerência

+
    +
  1. Escopo mal definido
  2. +
  3. Mudança arquitetural
  4. +
  5. Má gestão do tempo
  6. +
  7. Cronograma inviável
  8. +
  9. Má pontuação das US
  10. +
  11. Problema no gerenciamento da equipe
  12. +
  13. Sobrecarga de tarefas
  14. +
  15. Mudanças de tecnologias
  16. +
  17. Horários divergentes dos integrantes
  18. +
+

5. Externo

+
    +
  1. Suspensão das aulas
  2. +
  3. Baixa adesão da aplicação
  4. +
  5. Imprevistos com infraestrutura (internet, energia, computador)
  6. +
  7. Afastamento de integrante (enfermidade, luto, assistência familiar)
  8. +
  9. Atualizações drásticas das tecnologias escolhidas
  10. +
+

Monitoramento Contínuo dos Riscos

+

Gerenciar os riscos é um processo contínuo e dinâmico. Ao longo do desenvolvimento do projeto Sentinela, novos riscos podem surgir e os riscos existentes podem aumentar ou diminuir em impacto e probabilidade. É essencial que a equipe:

+
    +
  • Realize revisões regulares dos riscos identificados.
  • +
  • Esteja atenta a novos riscos que possam aparecer.
  • +
  • Ajuste as estratégias de mitigação conforme necessário.
  • +
  • Documente qualquer mudança no impacto e probabilidade dos riscos.
  • +
+

Esse monitoramento constante permite que a equipe reaja proativamente às mudanças e mantenha o controle sobre os fatores que podem afetar o sucesso do projeto.

+

Histórico de Versão

+ + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento22/07/24Victor Yukio
Atualização dos riscos08/09/24Ingrid Carvalho
Revisão08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/gestao/roadmap/index.html b/gestao/roadmap/index.html new file mode 100644 index 0000000..6167869 --- /dev/null +++ b/gestao/roadmap/index.html @@ -0,0 +1,2301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Entregas e roadmap - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Entregas e roadmap

+

O Roadmap do projeto foi criado a partir do que foi definido e validado na EAP e atualizado semanalmente conforme o andamento das atividades. Assim, os pacotes de trabalho foram representados no Roadmap, e épicos (funcionalidades do produto) foram associadas a eles. Os épicos, por fim, foram associados às Histórias de Usuário às quais se referiam.

+

Na data final de entrega do projeto, a situação do Roadmap era a seguinte:

+

Roadmap

+

O comportamento do roadmap, apesar de aparentar muitos atrasos, era o esperado para o fluxo de trabalho da disciplina, onde normalmente existe um período de espera da aceitação por parte dos P.Os e retorno de correções e melhorias. No geral, observa-se um bom prospecto, i.e das 16 US instanciadas para o projeto neste semestre (15 planejadas e 1 adicionada), foi possível entregar 14 delas.

+

As US foram divididas em 5 Releases totais (3 Major e 2 minors):

+

Release 1 (Major):

+
    +
  • US01 - Fazer login
  • +
  • US02 - Solicitar filiação
  • +
  • US04 - Cadastrar usuários
  • +
  • US33 - Atualizar dados de usuário
  • +
+

Release 2 (Minor):

+
    +
  • US17 - Cadastrar perfis no sistema
  • +
  • US05 - Cadastrar contas bancárias
  • +
+

Release 3 (Minor):

+
    +
  • US19 - Cadastrar benefícios
  • +
  • US02 - Solicitar filiação (Ajustes pedidos na Release 1)
  • +
  • US34 - Gerenciar filiações
  • +
+

Release 4/MVP (Major):

+
    +
  • US01 - Fazer login no sistema (Ajustes pedidos na Release 1)
  • +
  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release 3)
  • +
  • US16 - Visualizar dashboard sobre os sindicalizados
  • +
  • US20 - Cadastrar movimentações financeiras
  • +
  • US23 - Consulta do Histórico de Contribuições do sindicalizado
  • +
  • US35 - Cadastro de órgão/lotação
  • +
  • US34 - Gerenciar solicitações de filiação (Ajustes pedidos na Release 2)
  • +
+

Release 5/N (Major):

+
    +
  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release 4)
  • +
  • US20 - Cadastrar movimentações financeiras (Ajustes pedidos na Release 4)
  • +
  • US17 - Cadastrar perfis (Ajustes necessários identificados na Release 4)
  • +
  • US18 - Atribuir perfis
  • +
  • US21 - Gerar relatório de movimentações financeiras
  • +
  • ENH-US02 - Melhorias da US02
  • +
  • ENH-US05 - Melhorias da US05
  • +
+

Histórico de Versões

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..abeccfc --- /dev/null +++ b/index.html @@ -0,0 +1,2458 @@ + + + + + + + + + + + + + + + + + + + + + + + 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sentinela 2024.1

+

Este é o repositório de documentação do projeto Sentinela realizado pelos alunos das disciplinas de EPS e MDS para o SINDPOL-DF no primeiro semestre de 2024.

+

Repositórios do projeto

+ + + +

Integrantes do time

+

EPS

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NomeMatrículaUsuário Github
Sara Campos170045269@saracampss
Alvaro Gouvea180012002@algouvea
Ingrid Carvalho190029731@ingridscarvalho
Victor Yukio180068229@yukioz
+

MDS

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NomeMatrículaUsuário Github
Anna Brandão222006534@annacbrandao
Diogo Barboza222006660@Diogo-Barboza
Davi Mesquita222006650@davimesquit
Davi Nobre211062929@jagaima
Guilherme Storch211030765@storch7
Milena Rocha222022000@milenafrocha
João Victor Nobre202017423@Gam13
José Eduardo221008202@jevprado
+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento26/03/24Sara Campos
Correções28/03/24Sara Campos
Atualização dos repositórios do projeto18/07/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/lean/dia1/index.html b/lean/dia1/index.html new file mode 100644 index 0000000..330f77c --- /dev/null +++ b/lean/dia1/index.html @@ -0,0 +1,2355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Parte 1 - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Lean Inception - Dia 1

+

Visão do Produto

+

Nesta etapa, a proposta é definir de maneira colaborativa uma ideia inicial do que espera-se do produto através de uma frase clara que segue o formato:

+

Para: [cliente final],
+Cujo: [problema que precisa ser resolvido],
+O: [nome do produto]
+É um: [categoria do produto]
+Que: [benefício-chave, razão para adquiri-lo],
+Diferentemente do: [alternativa da concorrência]
+O nosso produto: [diferença-chave].

+

Reunião

+

Data: 01/04/24

+

Participantes:

+ + + + + + + + + + + + + + + + + + + + + +
EquipeNomes
POMatheus Amaral, Davi Mendonça
EPSIngrid Carvalho, Sara Campos, Victor Yukio, Alvaro Gouvea
MDSAnna Brandão, Guilherme Storch, Milena Rocha, José Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, João Victor Nobre
+

Descrição:

+

Em reunião, a dinâmica de Visão do Produto foi apresentada para o cliente e guiada pela estudante Ingrid Carvalho, ao passo que a estudante Sara Campos fazia as anotações no quadro Figma como pode ser observado aqui.

+

O objetivo neste momento foi, a partir do quadro criado no semestre 2023/2, validar o que havia sido levantado, além de corrigir possíveis erros, tentar deixar a frase mais clara e adicionar o que fosse necessário.

+

Por ser o primeiro contato dos estudantes com o produto, para tentar deixar essa etapa um pouco mais fluída, foi realizada no dia 28/03/24 uma reunião de "Pré Lean Inception" com o PO Matheus Amaral, que explicou brevemente a proposta do sistema e algumas coisas que deveríamos nos atentar neste momento. Assim, foi possível guiar melhor o PO e representante do SINDPOL Davi Mendonça na atividade e compreender bem o que foi passado.

+

Como resultado dessa reunião, conseguimos o seguinte quadro de Visão do Produto:

+

Visão do Produto

+

Ainda nesta reunião, foi iniciada a dinâmica de É/Nãoé - Faz/NãoFaz. Entretanto, o resultado do quadro só foi finalizado no 2º dia de Lean Inception.

+

Referências

+

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/04/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/lean/dia2/index.html b/lean/dia2/index.html new file mode 100644 index 0000000..6abf60f --- /dev/null +++ b/lean/dia2/index.html @@ -0,0 +1,2346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Parte 2 - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Lean Inception - Dia 2

+

É/Nãoé - Faz/NãoFaz (ENFN)

+

Nesta atividade, busca-se classificar o produto seguindo quatro diretrizes. O ENFN ajuda a esclarecer o produto através de uma dinâmica simples onde define-se: o que o produto é; o que o produto não é; o que o produto faz; e o que o produto não faz.

+

Reunião

+

Data: 02/04/24

+

Participantes:

+ + + + + + + + + + + + + + + + + + + + + +
EquipeNomes
POMatheus Amaral, Davi Mendonça
EPSIngrid Carvalho, Sara Campos
MDSJosé Eduardo, Diogo Barboza, Davi Nobre
+

Descrição:

+

Nesta reunião, a dinâmica de ENFN foi novamente apresentada para o cliente e guiada pela estudante Ingrid Carvalho, ao passo que a estudante Sara Campos fazia as anotações no quadro Figma como pode ser observado aqui.

+

É importante ressaltar que nessa data, o quadro ENFN foi retomado após um teste de usabilidade realizado com o protótipo 2023/2. As estudantes EPS presentes chegaram a conclusão de que a combinação do teste, onde navegou-se por uma versão do sistema juntamente com o PO Davi Mendonça, seguido pela ENFN ajudou bastante no esclarecimento do produto para os estudantes, assim como refrescou bastante a memória dos POs presentes que conseguiram trazer com facilidade várias características do produto para o quadro ENFN (especialmente na seção "Faz").

+

Como resultado dessa reunião, chegou-se ao seguinte quadro ENFN:

+

ENFN

+

Referências

+

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/04/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/lean/dia3/index.html b/lean/dia3/index.html new file mode 100644 index 0000000..a3233c5 --- /dev/null +++ b/lean/dia3/index.html @@ -0,0 +1,2407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Parte 3 - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Lean Inception - Dia 3

+

Objetivos do Produto

+

Nesse momento, a proposta é resumir o produto em seus objetivos. Assim, as funções esperadas que o produto execute são trazidas e clusterizadas.

+

Personas

+

As personas são representações dos usuários finais do produto e trazem de forma mais realista quais necessidades aquele produto se propõe a atender. Assim, o time consegue levantar as funcionalidades tendo em mente a pessoa que irá usar o sistema.

+

Reunião

+

Data: 08/04/24

+

Participantes:

+ + + + + + + + + + + + + + + + + + + + + +
EquipeNomes
POMatheus Amaral, Davi Mendonça
EPSIngrid Carvalho, Sara Campos, Alvaro Gouvea
MDSAnna Brandão, Guilherme Storch, Milena Rocha, José Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, João Victor Nobre
+

Descrição:

+

Em reunião, a dinâmica de Visão do Produto foi apresentada para o cliente e guiada pela estudante Sara Campos, ao passo que a estudante Ingrid Carvalho fazia as anotações no quadro Figma como pode ser observado aqui.

+

Neste encontro, iniciamos com os Objetivos do Produto que haviam sido levantados no semestre 2023/2, refinando os textos dos post-its, excluindo duplicatas, especificando os perfis de usuário em cada post-it, aglutinando clusters e adicionando um novo cluster que foi trazido pelos POs. Além disso, com os clusters validados, foi pedido ao PO Davi Mendonça que classificasse cada um por prioridade/urgência indo de 1 a 7. Dessa forma, chegou-se nesta reunião ao seguinte resultado:

+

Objetivos do Produto

+
+
+

Os Objetivos do Produto ainda devem ser revisados em comparação com o ENFN, a fim de garantir que nenhum objetivo/função levantado anteriormente tenha sido esquecido na fase anterior.

+
+
+

Em seguida, duas personas construídas no semestre 2023/2 foram refinadas e duas novas personas foram criadas. Como pode-se observar abaixo, foram validadas 1 persona Gestor, 2 personas Sindicalizados e 1 persona Advogada:

+

Personas +Personas +Personas +Personas

+
+
+

Como tem-se observado que o perfil de maior urgência é o de Gestor, outra persona Gestor deve ser construída e enviada para validação do cliente.

+
+
+

Foi observado também nessa reunião que há necessidade de maior participação por parte dos estudantes de MDS. Assim, para incentivar essa colaboração, os MDS foram divididos em dois times pra cuidar de algumas demandas.

+ + + + + + + + + + + + + + + + + + + + + + + +
TimeResponsável por guiarParticipantesDemanda
1Diogo BarbozaAnna Brandão, José Eduardo, João Victor NobreMelhorar a persona gestor, criar outra persona gestor (especificar melhor as necessidades dessas 2 personas) e fazer as jornadas de usuário de cada um
2Guilherme StorchDavi Nobre, Milena Rocha, Davi MesquitaConferir se tudo que está no ENFN está representado no objetivos do produto e, se não estiver, adicionar em seu respectivo cluster; Jornadas das personas sindicalizadas e advogada
+

A ideia é incentivar a colaboração entre os MDS que ainda não tiveram oportunidade de trabalhar juntos e aumentar a contribuição e o alinhamento do time, de forma que, os MDS se sintam mais incluídos e seguros em participar da reunião com o cliente.

+

As atividades que foram pedidas deles devem ser acompanhadas pelos estudantes EPS disponíveis em caso de dúvida, e revisadas antes de serem enviadas para validação do cliente.

+

Referências

+

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento09/04/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/lean/dia4/index.html b/lean/dia4/index.html new file mode 100644 index 0000000..56ebe47 --- /dev/null +++ b/lean/dia4/index.html @@ -0,0 +1,2389 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Parte 4 - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Lean Inception - Dia 4

+

Jornadas de Usuário

+

As Jornadas de Usuário são o passo a passo do que é executado pela persona para cumprir um objetivo. Assim, são criados estes fluxos de atividades considerando o perfil, comportamento e as necessidades de cada persona..

+

Brainstorming de funcionalidades

+

Para atender as necessidades das personas, as funcionalidades devem ser pensadas. Neste momento, a atividade requer que os participantes repassem pelos objetivos do produto e pelas jornadas para pensar de maneira mais modular em quais seriam as funcionalidades presentes no produto final enxuto.

+

Reunião

+

Data: 15/04/24

+

Participantes:

+ + + + + + + + + + + + + + + + + + + + + +
EquipeNomes
POMatheus Amaral, Davi Mendonça
EPSIngrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio
MDSAnna Brandão, Guilherme Storch, Milena Rocha, José Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, João Victor Nobre
+

Descrição:

+

Como descrito no dia 3, os estudantes de MDS ficaram responsáveis por se organizar para realizar algumas atividades. Assim, os estudantes construíram as jornadas de usuário que posteriormente foram refinadas pelos estudantes de EPS. Além disso, duas novas personas foram criadas conforme foi identificado que era necessário.

+

Durante a reunião com os POs, foram apontadas algumas correções que, por fim, resultaram nas seguintes personas e suas respectivas jornadas:

+

Persona 1 + Jornada: +P1 +J1

+

Persona 2 + Jornada: +P2 +J2

+

Persona 3 + Jornada: +P3 +J3

+

Persona 4 + Jornada: +P4 +J4

+

Persona 5 + Jornada: +P5 +J5

+

Persona 6 + Jornada: +P6 +J6

+

Com essa parte realizada, iniciamos nosso Brainstoming de Funcionalidades. Os resultados, no entanto, só foram alcançados no dia 5.

+

Referências

+

Journey Mapping 101
+Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento15/04/24Sara Campos
Alteração do relato do dia 4 (12/04) para reunião com cliente (15/04)Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/lean/dia5/index.html b/lean/dia5/index.html new file mode 100644 index 0000000..cba86a3 --- /dev/null +++ b/lean/dia5/index.html @@ -0,0 +1,2330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Parte 5 - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Lean Inception - Dia 5

+

Reunião

+

Data: 17/04/24

+

Participantes:

+ + + + + + + + + + + + + + + + + + + + + +
EquipeNomes
POMatheus Amaral, Davi Mendonça
EPSIngrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio
MDSGuilherme Storch, José Eduardo, Diogo Barboza, Davi Mesquita, João Victor Nobre
+

Descrição:

+

Nesta reunião, a proposta era finalizar o Brainstorming de Funcionalidades. As funcionalidades são representadas em post-its amarelos, enquanto em verde temos algumas notas que trazem detalhes a serem considerados sobre as respectivas funcionalidades.

+
+
+

O resultado mostrado nas imagens a seguir conta com alterações realizadas após uma conversa no dia 19/04 com Lucas Neves, advogado representante da área jurídica do sindicato. Este encontro não foi considerado um dia de Lean Inception por sua breviedade (duração de 15 minutos), mas ressalta-se que foi um momento importante que ajudou a confirmar e refinar as necessidades do jurídico anteriormente apontadas pelos POs Matheus e Davi.

+
+
+

Brainstorming +Brainstorming

+

Referências

+

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento23/04/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/lean/dia6/index.html b/lean/dia6/index.html new file mode 100644 index 0000000..baa3be8 --- /dev/null +++ b/lean/dia6/index.html @@ -0,0 +1,2351 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Parte 6 - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Lean Inception - Dia 6

+

Revisão técnica e de negócio

+

Com as funcionalidades pensadas, chega a hora de classificá-las. O método propõe duas formas de classificação:

+
    +
  1. posicionando num gráfico onde o eixo Y refere-se ao quanto a funcionalidade agrega valor ao produto, enquanto no eixo X qual seria a confiança do time em executar a tarefa;
  2. +
  3. conferindo ao post-it com a funcionalidade valor de esforço, valor de negócio e valor de UX.
  4. +
+

Dessa forma, tem-se o seguinte formato de classificação para os post-its:

+

Revisão técnica e de negócio

+

Reunião

+

Data: 22/04/24

+

Participantes:

+ + + + + + + + + + + + + + + + + + + + + +
EquipeNomes
POMatheus Amaral, Davi Mendonça
EPSIngrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio
MDSAnna Brandão, Guilherme Storch, Milena Rocha, José Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, João Victor Nobre
+

Descrição:

+

Para essa reunião, o grupo de estudantes havia se reunido logo antes para preparar a Revisão Técnica e de Negócio. Dessa forma, deixou-se para o momento agendado com o cliente apenas a definição dos valores de negócio. Durante o encontro, a discussão sobre os valores de negócio de cada funcionalidade foi iniciada, mas a atribuição foi finalizada de modo assíncrono pelo PO Davi.

+

Rev Técnica e de Negócio +Rev Técnica e de Negócio

+

Referências

+

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento02/05/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/lean/dia7/index.html b/lean/dia7/index.html new file mode 100644 index 0000000..5aca02f --- /dev/null +++ b/lean/dia7/index.html @@ -0,0 +1,2333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Parte 7 - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Lean Inception - Dia 7

+

Reunião

+

Data: 22/04/24 - 15/07/24

+

Participantes:

+ + + + + + + + + + + + + + + + + + + + + +
EquipeNomes
POMatheus Amaral, Davi Mendonça
EPSIngrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio
MDSAnna Brandão, Guilherme Storch, Milena Rocha, José Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, João Victor Nobre
+

Descrição:

+

No último dia, a intenção era construir o Sequenciador, artefato valioso para as estimativas de tempo e escopo do projeto. Seguindo as intruções de criação do Sequenciador, as funcionalidades foram posicionadas nas raias e o MVP foi definido. Com isso, o time fez o Dimensionamento de Tarefas, que consiste em pegar amostras de raias com funcionalidades, detalhar em Histórias de Usuário, estimar o tamanho e o tempo de cada raia da amostra e assim chegar a uma média de tempo por raia. Esse processo pode ser observado na figura abaixo.

+

Dimensionamento de tarefas

+

Com o dimensionamento feito, o Sequenciador visto abaixo estava pronto para ser validado pelo cliente, o que foi feito de maneira remota.

+

Sequenciador

+

Com o retorno das atividades após o período de greves foi apresentado ao cliente o último artefato do Lean Inception, o Canvas MVP:

+

Canvas MVP

+

Referências

+

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento02/05/24Sara Campos
Atualização18/07/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/prototipagem/idv/index.html b/prototipagem/idv/index.html new file mode 100644 index 0000000..9937803 --- /dev/null +++ b/prototipagem/idv/index.html @@ -0,0 +1,2312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Identidade Visual - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Identidade Visual

+

Na reunião com o cliente do dia 1º de abril foi apresentada e aprovada a nova identidade visual (IDV) do produto.

+

A nova IDV conta com uma paleta de cores selecionada trazendo identificação para o SINDPOL, além passar mensagens de comprometimento, organização e elegância para o usuário. Foi realizado teste de contraste com a paleta de cores para validar a leiturabilidade para pessoas com daltonismo e outras deficiências que impactem a percepção das cores. Além disso, com a paleta de cores foram geradas 55 variáveis de cores para serem usadas no protótipo mantendo a identidade visual.

+

Com relação a tipografia, foram escolhidas duas fontes sem-serifa que passam modernidade e seriedade para o usuário ao interagir com o produto. As fontes contém também grande cobertura de caracteres e alta variabilidade de estilos, pesos e comprimentos. Os ícones que devem ser usados no produto, seguindo a mesma ideia da tipografia, serão do pacote Ant Design Icons da biblioteca React Icons.

+

Proposta de Identidade Visual apresentada e aprovada

+ + +

Referências

+

Colormind.io
+Constrast Checker
+UI Colors
+Google Fonts - Noto Sans
+Google Fonts - Overpass
+React Icons - Ant Design Icons

+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento02/04/24Sara Campos
Atualização03/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/prototipagem/prototipo/index.html b/prototipagem/prototipo/index.html new file mode 100644 index 0000000..09c66cd --- /dev/null +++ b/prototipagem/prototipo/index.html @@ -0,0 +1,2264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Protótipo de alta fidelidade - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Protótipo de alta fidelidade

+

O time decidiu sempre desenvolver protótipos de alta fidelidade para o produto, utilizando da Identidade Visual e das discussões com os P.Os. Dessa forma, nas semanas inicias de desenvolvimento os EPS se encarregaram de prototipar as telas das US, mas logo foi realizado o Dojo de Figma e, assim, os MDS puderam também começaram a trabalhar com protótipos.

+

Abaixo é possível visualizar o protótipo navegável, e o Figma onde tudo foi desenvolvido pode ser acessado também ao clicar aqui. Em todas as US foram anexados também links para os protótipos.

+ + + + +

Histórico de Versões

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/prototipagem/testesusabilidade/index.html b/prototipagem/testesusabilidade/index.html new file mode 100644 index 0000000..2aeb6ce --- /dev/null +++ b/prototipagem/testesusabilidade/index.html @@ -0,0 +1,2355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Testes de usabilidade - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Testes de usabilidade

+

Ao longo do período letivo de 2024/1 serão realizados alguns testes de usabilidade com o cliente para entender melhor como o sistema pode se adequar às necessidades dele e validar decisões de design na prototipagem.

+

Teste de usabilidade 1

+

No intuito de compreender melhor o sistema e identificar possíveis melhorias, para o primeiro teste de usabilidade (realizado em 02 de abril) foi utilizado o protótipo navegável construído no semestre 2023/2, como pode-se observar abaixo.

+ + +

Algumas descobertas/possibilidades de melhoria identificadas no teste com o usuário:

+
    +
  • +

    É necessário diferenciar login para os tipos de perfis (gestor/sindicalizado), neste protótipo os fluxos não diferenciam os tipos de permissão de cada perfil

    +
  • +
  • +

    O cliente vê urgência no desenvolvimento do sistema com funcionalidades para o perfil de gestor

    +
  • +
  • +

    Formulário de filiação

    +
  • +
  • +

    O cliente disponibilizou arquivo com maiores instruções

    +
  • +
  • +

    Lembrete: dar sempre a opção de voltar para página anterior

    +
  • +
  • +

    Página inicial ao logar no sistema

    +
  • +
  • +

    No sistema atual encontra-se um dashboard com estatísticas sobre os sindicalizados

    +
  • +
  • +

    Gerar documentos

    +
  • +
  • +

    Para o perfil de filiado/sindicalizado → emissão de carteirinha e declaração de vínculo

    +
  • +
  • +

    Para o perfil de gestor → inserir dados do sindicalizado e emitir os documentos

    +
  • +
  • +

    Desfiliação

    +
  • +
  • +

    Quando o usuário clica em configurações já abre direto nessa aba

    +
  • +
  • Para o perfil de gestor → espera-se formulário conforme o requerimento que eles já usam atualmente e opção de gerar PDF para o sindicalizado assinar
  • +
  • +

    Para o perfil de filiado → recebe PDF pra assinar e enviar de volta pro gestor como confirmação da desfiliação

    +
  • +
  • +

    Relatórios

    +
  • +
  • +

    Sugestão para validar com cliente: transformar em uma opção presente em todas as áreas passíveis de gerar relatório, desde o dashboard da página inicial a outras funcionalidades

    +
  • +
  • +

    Patrimônios

    +
  • +
  • +

    Área de registro para controle do patrimônio

    +
  • +
  • Escala estado/conservação não faz muito sentido, como mensurar?
      +
    • Sugestão para validar com cliente: colocar em forma de perguntas: tem defeitos funcionais? o uso é afetado pela depreciação? tem marcas de uso?
    • +
    +
  • +
  • Material para doação → registrar para onde foi
      +
    • Sugestão: checkbox no formulário de cadsastro do patrimônio para informar se foi feita a doação do patrimônio, quando marcado abre outra part4e do formulária que registra para onde foi
    • +
    +
  • +
  • Necessidade de uma listagem de patrimônios (avaliar se é necessária a opção de filtragem)
  • +
+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento03/04/24Sara Campos
Registro do teste de usabilidade 103/04/24Sara Campos
Atualização03/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/planning/index.html b/ritos/planning/index.html new file mode 100644 index 0000000..24b73ea --- /dev/null +++ b/ritos/planning/index.html @@ -0,0 +1,2257 @@ + + + + + + + + + + + + + + + + + + + + + Sprint Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Sprint Planning

+

O que é Sprint Planning?

+

A Sprint Planning é uma reunião que dá início a cada Sprint no framework Scrum. O principal objetivo dessa reunião é definir o trabalho a ser realizado na próxima Sprint, criando um plano claro e compartilhado pela equipe de desenvolvimento. A Sprint Planning garante que todos os membros da equipe estejam alinhados quanto às metas e tarefas a serem executadas, além de preparar o backlog da Sprint com as histórias e tarefas selecionadas.

+

Objetivos da Sprint Planning

+
    +
  • Definir o Objetivo da Sprint: Estabelecer uma meta clara e alcançável que a equipe se compromete a atingir ao final da Sprint.
  • +
  • Selecionar Itens do Backlog do Produto: Escolher os itens de maior prioridade do backlog do produto que a equipe acredita ser capaz de completar durante a Sprint.
  • +
  • Criar o Backlog da Sprint: Dividir os itens selecionados em tarefas menores e mais gerenciáveis, criando um backlog da Sprint bem definido.
  • +
+

Participantes

+

1) Scrum Team: Inclui o Scrum Master, o Product Owner e a equipe de desenvolvimento.

+

Estrutura da Sprint Planning

+

A Sprint Planning geralmente é dividida em duas partes principais:

+

Parte 1: O que será feito na Sprint?

+

Apresentação dos Itens do Backlog do Produto: O Product Owner apresenta os itens de backlog mais prioritários e fornece o contexto necessário para a equipe.

+

Discussão dos Itens: A equipe de desenvolvimento faz perguntas e esclarece dúvidas sobre os itens apresentados, garantindo uma compreensão completa das tarefas a serem realizadas.

+

Seleção dos Itens para a Sprint: Com base na prioridade e na capacidade da equipe, os itens do backlog são selecionados para a Sprint.

+

Parte 2: Como o trabalho será feito?

+

Planejamento das Tarefas: Os itens selecionados são divididos em tarefas menores e detalhadas, que serão distribuídas entre os membros da equipe.

+

Estimativas de Tempo e Esforço: A equipe de desenvolvimento estima o tempo e o esforço necessários para completar cada tarefa, ajustando conforme necessário.

+

Criação do Backlog da Sprint: Todas as tarefas planejadas são reunidas para formar o backlog da Sprint, com uma visão clara do que será feito e como será realizado.

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/retrospective/index.html b/ritos/retrospective/index.html new file mode 100644 index 0000000..2898182 --- /dev/null +++ b/ritos/retrospective/index.html @@ -0,0 +1,2240 @@ + + + + + + + + + + + + + + + + + + + + + Sprint Retrospectiva - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+ +
+ + + +
+
+ + + + + + + +

Sprint Retrospectiva

+

O que é a Sprint Retrospectiva?

+

A Sprint Retrospectiva é uma reunião realizada ao final de cada Sprint no framework Scrum. O objetivo principal dessa reunião é permitir que a equipe Scrum reflita sobre o processo de trabalho utilizado durante a Sprint e identifique oportunidades de melhoria contínua. É um momento para a equipe avaliar o que funcionou bem, o que não funcionou e como os processos podem ser aprimorados para a próxima Sprint.

+

Objetivos da Sprint Retrospectiva

+

Refletir sobre a Sprint: Analisar como a Sprint transcorreu em termos de pessoas, relações, processos e ferramentas. +Identificar Melhorias: Destacar as áreas que precisam de melhorias e identificar ações concretas para implementar essas melhorias. +Promover a Melhoria Contínua: Desenvolver um plano de ação que a equipe possa seguir para aumentar a eficiência e a eficácia nas próximas Sprints.

+

Participantes

+

1) Scrum Team: Inclui o Scrum Master, o Product Owner e a equipe de desenvolvimento.

+

Estrutura da Sprint Retrospectiva

+

A Sprint Retrospectiva pode variar em formato e técnicas, mas geralmente inclui os seguintes elementos:

+
    +
  1. Preparação +Ambiente Seguro: O Scrum Master cria um ambiente seguro e aberto onde todos se sintam confortáveis para compartilhar suas opiniões e ideias. +Definição da Agenda: O Scrum Master apresenta a agenda da reunião e define as expectativas.
  2. +
  3. Reflexão sobre a Sprint +O que Funcionou Bem?: A equipe discute e anota os aspectos positivos da Sprint, identificando práticas e processos que foram eficazes. +O que Não Funcionou?: A equipe analisa os desafios e problemas enfrentados durante a Sprint, discutindo os pontos que precisam ser melhorados.
  4. +
  5. Identificação de Melhorias +Brainstorming: A equipe realiza uma sessão de brainstorming para gerar ideias de melhorias. +Priorizar Melhorias: As sugestões de melhorias são priorizadas com base no impacto e na viabilidade.
  6. +
  7. Desenvolvimento de um Plano de Ação +Ações Concretas: A equipe define ações concretas e específicas para implementar as melhorias identificadas. +Responsáveis e Prazos: Cada ação recebe um responsável e um prazo para implementação, garantindo que as melhorias sejam acompanhadas e realizadas.
  8. +
  9. Fechamento +Revisão Final: A equipe revisa o plano de ação e garante que todos estejam alinhados e comprometidos. +Agradecimentos: O Scrum Master agradece a participação de todos e encerra a reunião.
  10. +
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/review/index.html b/ritos/review/index.html new file mode 100644 index 0000000..06984d0 --- /dev/null +++ b/ritos/review/index.html @@ -0,0 +1,2235 @@ + + + + + + + + + + + + + + + + + + + + + Sprint Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint Review

+

O que é Sprint Review?

+

A Sprint Review é um evento fundamental no Scrum, uma das metodologias ágeis mais populares. Acontece ao final de cada Sprint, que é um ciclo de desenvolvimento com duração fixa (geralmente de duas a quatro semanas). O objetivo principal da Sprint Review é inspecionar o incremento do produto e adaptar o backlog do produto conforme necessário.

+

Objetivos da Sprint Review

+
    +
  • +

    Inspecionar o Incremento: Avaliar o trabalho concluído durante a Sprint. O incremento é a soma de todos os itens do backlog do produto completados durante a Sprint, que são potencialmente entregáveis e prontos para uso.

    +
  • +
  • +

    Receber Feedback: Permitir que o Product Owner e os stakeholders forneçam feedback sobre o incremento, possibilitando ajustes e alinhamentos com as expectativas do cliente.

    +
  • +
+

8 Adaptar o Backlog do Produto: Com base no feedback recebido e na inspeção do incremento, ajustar e priorizar o backlog do produto, preparando-o para a próxima Sprint.

+

Participantes

+

1) Scrum Team: Inclui o Scrum Master, o Product Owner e a equipe de desenvolvimento.

+

2) Stakeholders: Clientes, usuários finais, gerentes e outros interessados no desenvolvimento do produto.

+

Estrutura da Sprint Review

+

A Sprint Review segue um formato estruturado, incluindo as seguintes etapas:

+

1) Apresentação do Incremento: A equipe de desenvolvimento demonstra o trabalho concluído. Isso pode incluir uma demonstração de novas funcionalidades, melhorias e correções.

+

2) Discussão sobre o Produto: O Product Owner discute o estado atual do backlog do produto e o progresso em direção à meta do produto.

+

3) Feedback dos Stakeholders: Os stakeholders fornecem feedback sobre o incremento. Este é um momento crucial para garantir que o desenvolvimento do produto esteja alinhado com as necessidades e expectativas dos usuários.

+

4) Revisão e Adaptação do Backlog: Com base no feedback, o backlog do produto é atualizado. Novas histórias podem ser adicionadas, e a priorização pode ser ajustada para refletir as mudanças nas necessidades do negócio. Qualquer débito técnico será discutido e ganhará destaque para o planejamento da próxima sprint.

+

5) Planejamento para a Próxima Sprint: Embora o foco principal da Sprint Review não seja o planejamento da próxima Sprint, algumas discussões preliminares podem ocorrer, preparando o terreno para a Sprint Planning.

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/inicio/retomada_inicio/index.html b/ritos/sprints/inicio/retomada_inicio/index.html new file mode 100644 index 0000000..8d98069 --- /dev/null +++ b/ritos/sprints/inicio/retomada_inicio/index.html @@ -0,0 +1,2271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retomada às atividades - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva de retomada de atividades

+

Com a retomada das atividades após o período de greve, foi feita uma retrospectiva em sala aula com as turmas de EPS e MDS que resultou em três reflexões principais.

+

1) Dificuldade de comunicar com o cliente.

+

2) Horário das agendas.

+

3) Updates de EPS para mds.

+

retro_sprint0

+

As três principais dores do time foram encaminhadas nas atividades seguintes. A comunicação com o clinente apresentou melhora, assim como com o time, além da agenda, participação e união dos membros ter aumentado notavelmente.

+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento15/07/24Victor Yukio
Revisão18/07/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/inicio/retrospec_inicio/index.html b/ritos/sprints/inicio/retrospec_inicio/index.html new file mode 100644 index 0000000..d41ece2 --- /dev/null +++ b/ritos/sprints/inicio/retrospec_inicio/index.html @@ -0,0 +1,2287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retrospectiva - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva inicial

+

Nos dias iniciais da Sprint 1 foi realizada uma retrospectiva de maneira remota que gerou algumas reflexões.

+

Pontos positivos e negativos

+

retro_sprint0

+

Na coluna "Estrelas da Retro" foram colocados os cards que tiveram mais reconhecimento do time, dos quais alguns foram encaminhados (como a planilha de datas provas, para melhorar o monitoramento de disponiblidade assim como de riscos), e outros (como comportamentos gerais do time) esperam ser mantidos.

+

Histórico de versão

+ + + + + + + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento15/07/24Victor Yukio
Revisão18/07/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint1/pareamentos1/index.html b/ritos/sprints/sprint1/pareamentos1/index.html new file mode 100644 index 0000000..eb89dc3 --- /dev/null +++ b/ritos/sprints/sprint1/pareamentos1/index.html @@ -0,0 +1,2308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pareamentos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Pareamentos

+

Na Sprint 1, ocorreram quatro pareamentos, de forma que todos participantes de MDS foram alocados em uma das US. Para a US01, foi definido um Squad responsável, que dividiu a tarefa na preparação dos ambientes de frontend e backend, assim como o código fonte da US em questão. As alocações podem ser observadas nas tabelas abaixo:

+ + + + + + + + + + + + + + + +
SquadUSDescrição
Álvaro, Ingrid, Sara e VictorUS01Fazer login
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PareamentoUSDescrição
Guilherme e MilenaUS02Solicitar filiação
Anna e Davi MesquitaUS03Cadastrar fornecedores
Davi Nobre e João Victor NobreUS04Cadastrar usuários
Diogo e José EduardoUS33Atualizar dados do perfil
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento06/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint1/planning1/index.html b/ritos/sprints/sprint1/planning1/index.html new file mode 100644 index 0000000..2e52769 --- /dev/null +++ b/ritos/sprints/sprint1/planning1/index.html @@ -0,0 +1,2342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 1

+

Planning

+

Data: 12/07/24

+

Objetivos da Sprint Planning

+

Para a Sprint 1, foram selecionadas histórias de usuário do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time com foco na entrega da Release 1, que se daria em duas sprints. Das seis histórias de usuário esperadas para entrega na Release 1, cinco foram distribuídas já na Sprint 1 conforme os pareamentos definidos.

+

Estrutura da Sprint Planning

+

As histórias de usuário definidas pro sprint backlog foram:

+
    +
  • US01 - Fazer login
  • +
  • US02 - Solicitar filiação
  • +
  • US03 - Cadastrar fornecedores
  • +
  • US04 - Cadastrar usuários
  • +
  • US33 - Atualizar dados do usuário como sindicalizado
  • +
+

Nessa reunião foram especificados os critérios de aceitação de cada uma das seis US da Release 1 e cada uma foi encaminhada para prototipagem. A US01 (Fazer login) teve um caminho diferente, pois foi uma User Storie que viabilizou a preparação de ambiente e início do códgio fonte, portanto esta já havia sido preparada antes da planning.

+

Além dos critérios de aceitação e protótipos, foram definidos os pontos por história de cada US, utilizando uma ferramenta online para o Planning Poker. Ao fim, foram estabelecidos os pareamentos que deveriam trabalhar em cada US durante a sprint que se iniciaria.

+

Com o que foi definido na reunião de planning e os protótipos concebidos nos dias que se seguiram, foi possível validar as US com os POs e, por fim, iniciar o desenvolvimento do código fonte.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento06/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint1/review1/index.html b/ritos/sprints/sprint1/review1/index.html new file mode 100644 index 0000000..73d8cbb --- /dev/null +++ b/ritos/sprints/sprint1/review1/index.html @@ -0,0 +1,2308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Review

+ +

Review

+

Data: 22/07/24

+

Estrutura da Sprint Review

+

Junto dos POs, foram tiradas dúvidas sobre o desenvolvimento e definidas práticas de escrita mais detalhada das US e de comunicação com os POs. Sobre a US01 foram esclarecidos detalhes de como estava sendo feita a autenticação e ficou acordado que os POs enviariam o texto modelo pro e-mail que o usuário recebe na recuperação de senha. Os responsáveis pelas outras US também apresentaram o andamento do trabalho.

+

Houve a apresentação das datas das releases pro cliente com o Canvas MVP e o Roadmap. Foram também colocadas para validação as US da Sprint 3. Foi definido nesta reunião que a apresentação da Releasse 1 ocorreria no dia 30/07/24 às 20h.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint2/pareamentos2/index.html b/ritos/sprints/sprint2/pareamentos2/index.html new file mode 100644 index 0000000..39e99f7 --- /dev/null +++ b/ritos/sprints/sprint2/pareamentos2/index.html @@ -0,0 +1,2297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pareamentos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Pareamentos

+

Na Sprint 2, ocorreram também quatro pareamentos, de forma que todos participantes de MDS foram alocados em pelo menos uma das US. Nessa Sprint os estudantes de EPS se encarregaram de auxiliar nas US necessárias e de outras responsabilidades, como documentações e DevOps. As alocações podem ser observadas nas tabelas abaixo:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PareamentoUSDescrição
Guilherme e MilenaUS02Solicitar filiação
Guilherme e MilenaUS05Cadastrar contas bancárias
Anna e Davi MesquitaUS03Cadastrar fornecedores
Davi Nobre e João Victor NobreUS04Cadastrar usuários
Diogo e José EduardoUS33Atualizar dados do perfil
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento06/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint2/planning2/index.html b/ritos/sprints/sprint2/planning2/index.html new file mode 100644 index 0000000..bcde498 --- /dev/null +++ b/ritos/sprints/sprint2/planning2/index.html @@ -0,0 +1,2342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 2

+

Planning

+

Data: 19/07/24

+

Objetivos da Sprint Planning

+

Para a Sprint 2, foram selecionadas histórias de usuário do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time com foco na entrega da Release 1, que se daria ao fim dessa sprint. Das seis histórias de usuário esperadas para entrega na Release 1, apenas uma nova foi colocada no Sprint Backlog. Todos os pareamentos ainda estavam trabalhando nas US definidas anteriormente, mesmo que fossem pequenas finalizações.

+

Estrutura da Sprint Planning

+

As histórias de usuário definidas pro sprint backlog foram:

+
    +
  • US01 - Fazer login
  • +
  • US02 - Solicitar filiação
  • +
  • US03 - Cadastrar fornecedores
  • +
  • US04 - Cadastrar usuários
  • +
  • US33 - Atualizar dados do usuário como sindicalizado
  • +
  • US05 - Cadastrar contas bancárias
  • +
+

Nessa reunião os estados de cada US foi alinhado entre todos os integrantes, foram mantidos os pareamentos anteriores e definido um pareamento que parecia mais próximo de finalizar as tarefas da Sprint 1 para assumir a US05 assim que possível.

+

Foram especificadas também as US previstas pra Sprint 3, a fim de ter validação dos POs com antecedência.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento06/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint2/retrospectiva/index.html b/ritos/sprints/sprint2/retrospectiva/index.html new file mode 100644 index 0000000..4a8b9fe --- /dev/null +++ b/ritos/sprints/sprint2/retrospectiva/index.html @@ -0,0 +1,2283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retro - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva da Release 1

+

Pontos positivos e negativos

+

retro2207

+

Foi bem: muito aprendizado e produtividade dos MDS, apoio dos EPS, interação e comprometimento do grupo

+

Deu errado: estimativas de tempo para entrega e conhecimento raso sobre as tecnologias

+

Lições aprendidas: iniciar a sprint com tudo já validado e estimar melhor o tempo da sprint pensando em desenvolvimento e testes

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint2/review2/index.html b/ritos/sprints/sprint2/review2/index.html new file mode 100644 index 0000000..8dfb36d --- /dev/null +++ b/ritos/sprints/sprint2/review2/index.html @@ -0,0 +1,2427 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Review

+ +

Review

+

Data: 22/07/24
+Facilitadora: Ingrid
+Responsáveis pela ata: Milena e Guilherme

+

Estrutura da Sprint Review

+

Como encaminhamento da Release 1, o time escolheu iniciar uma prática de ter um facilitador EPS a cada semana na reunião com PO, ao passo que dois estudantes de MDS devem ficar responsáveis por anotações da reunião.

+

Participantes:

+
    +
  • Alvaro Henrique de Sousa Gouveaa
  • +
  • Anna Clara Cardoso Evangelista
  • +
  • Davi Dos Santos Brito
  • +
  • Diogo Rodrigues Barboza
  • +
  • Guilherme Storch De Oliveira
  • +
  • Ingrid da Silva Carvalho
  • +
  • João Victor Carvalho Nobre
  • +
  • Jose Eduardo Vieira Do Prado
  • +
  • Milena Fernandes Rocha
  • +
  • Sara Paula Lima Campos
  • +
  • Victor Yukio Cavalcanti
  • +
  • Davi Mendonça
  • +
  • Matheus Amaral
  • +
+

Pauta:

+
    +
  • Revisar as US finalizadas e em andamento.
  • +
  • Validar os critérios de aceitação das possíveis US para a Sprint 4.
  • +
+

Observações

+

Os PO’s do projeto foram atualizados sobre as US’s em andamento. Foi apresentado os critérios de aceitação das histórias de usuário candidatas para a Sprint 4.

+
    +
  • US-16: Houve apresentação dos critérios de aceitação da User Story;
  • +
  • US-20: Houve complementação dos critérios de aceitação; nessa US, haverá a necessidade de colocar o saldo do início e do final do mês.
  • +
  • US-21: Houve apresentação dos critérios de aceitação da User Story e confirmação do que foi levantado pelo grupo por parte do PO;
  • +
  • US-22: Houve complementação dos critérios de aceitação
  • +
+

Decisões

+
    +
  • Haverá revisão e complementação dos critérios de aceitação pelo Mendonça da US-16. Data limite estipulada: 06/08/2024.
  • +
  • Haverá complementação dos critérios de aceitação da US-22 - restrições do usuário sindicalizado.
  • +
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Guilherme, Milena e Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint3/pareamentos3/index.html b/ritos/sprints/sprint3/pareamentos3/index.html new file mode 100644 index 0000000..246fdea --- /dev/null +++ b/ritos/sprints/sprint3/pareamentos3/index.html @@ -0,0 +1,2287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pareamentos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Pareamentos

+

Na Sprint 3, ocorreram também três pareamentos, de forma que todos participantes de MDS foram alocados em uma das US. Nessa Sprint os estudantes de EPS se encarregaram de auxiliar nas US necessárias, na realização dos testes e de outras responsabilidades, como documentações e DevOps. As alocações podem ser observadas nas tabelas abaixo:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
PareamentoUSDescrição
Guilherme e MilenaUS34Gerenciar filiações
Anna, Diogo e José EduardoUS19Cadastrar benefícios e convênios
Davi Nobre, Davi Mesquita e João Victor NobreUS17Cadastrar perfis com permissões
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento06/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint3/planning3/index.html b/ritos/sprints/sprint3/planning3/index.html new file mode 100644 index 0000000..dcfec5b --- /dev/null +++ b/ritos/sprints/sprint3/planning3/index.html @@ -0,0 +1,2342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 3

+

Planning

+

Data: 26/07/24

+

Objetivos da Sprint Planning

+

Para a Sprint 3, foram selecionadas histórias de usuário do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribuídas três histórias de usuário conforme os pareamentos definidos.

+

Estrutura da Sprint Planning

+

As histórias de usuário definidas pro sprint backlog foram:

+
    +
  • US34 - Gerenciar filiações
  • +
  • US19 - Cadastrar benefícios e convênios
  • +
  • US17 - Cadastrar perfis com permissões no sistema
  • +
+

Como já haviam sido especificados e validados os critérios de aceitação e protótiops de cada uma das US de forma assíncrona, foram definidos os pareamentos responsáveis por cada uma.

+

Além dos critérios de aceitação e protótipos, foram definidos os pontos por história de cada US, utilizando uma ferramenta online para o Planning Poker.

+

Algumas US da Sprint 2 seguiram sendo finalizadas nos dias seguintes, como foco na entrega da Release 1, que se daria no dia 29/07/24. As US puxadas para o Backlog da Sprint 3 foram iniciadas conforme as US da Release 1 foram finalizadas.

+

Após a apresentação da Release 1, em 30/07/24, os participantes também se encarregaram de dar continuidade aos encaminhamentos apontados pelo professor, tanto de documentação quanto de DevOps.

+

Nessa sprint também ficou definida uma mudança nas datas de review e planning para se adequar à data de reunião com cliente e melhorar o fluxo de trabalho do grupo. Dessa forma, a sprint não foi finalizada, como seria esperado, no dia 02/08/24, mas no dia 05/08/24, quando ocorreu a review da Sprint 3 e a Planning da Sprint 4.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento06/08/24Guilherme, Milena e Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint3/retrospectiva/index.html b/ritos/sprints/sprint3/retrospectiva/index.html new file mode 100644 index 0000000..096dfc2 --- /dev/null +++ b/ritos/sprints/sprint3/retrospectiva/index.html @@ -0,0 +1,2282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retro - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva 29/07

+

Pontos positivos e negativos

+

retro2907

+

Coisas boas: conduta e apoio dos EPS, conhecimento e ritmo de trabalho do MDS e validações de US.

+

Coisas ruins: problemas referentes ambiente, volume de trabalho e erros cometidos.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint3/review3/index.html b/ritos/sprints/sprint3/review3/index.html new file mode 100644 index 0000000..59638be --- /dev/null +++ b/ritos/sprints/sprint3/review3/index.html @@ -0,0 +1,2401 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Review

+ +

Review

+

Data: 05/08/24 +Facilitador: Alvaro
+Responsáveis pela ata: Anna e Guilherme

+

Participantes:

+
    +
  • Alvaro Henrique de Sousa Gouveaa
  • +
  • Anna Clara Cardoso Evangelista
  • +
  • Davi Dos Santos Brito
  • +
  • Diogo Rodrigues Barboza
  • +
  • Guilherme Storch De Oliveira
  • +
  • Ingrid da Silva Carvalho
  • +
  • João Victor Carvalho Nobre
  • +
  • Jose Eduardo Vieira Do Prado
  • +
  • Milena Fernandes Rocha
  • +
  • Sara Paula Lima Campos
  • +
  • Matheus Amaral
  • +
+

Pauta:

+

Alinhamento sobre o roadmap do projeto; +Validação dos protótipos das US’s: 21, 22, 23, 24. +Validação das Us’s para a próxima release: 19, 02,

+

Observações

+

Foram validadas as US’s 21, 22, 23, com algumas ressalvas em seus respectivos protótipos; +A US 21 - gerar relatório financeiro - Não possui critérios de aceitação claros; foi alinhado com o P.O. a respeito das sua especificidade. Será feito um ajuste no protótipo para futura validação; +Na US 22 - acessar prestação de contas do sindicato, o P.O. sugeriu inserir na view do sindicalizado uma label com o valor gasto para cada movimentação do sindicato, bem como um filtro de pesquisa de cada um dos valores gastos pelo sindicato. Serão trocadas as labels “Saldo inicial” e “Saldo final” para “entrada” e “saída”. Será feito um ajuste no protótipo para futura validação; +Na US 23 - Consulta do histórico de contribuição do sindicalizado, o P.O. sugeriu inserir na view uma label com o valor gasto para cada contribuição do sindicalizado, bem como o valor total no intervalo selecionado na filtragem. Existem 4 tipos de contribuição. Será feito um ajuste no protótipo para futura validação; +Na US 24 - Acessar histórico de contribuição como sindicalizado, o P.O. sugeriu inserir na view do sindicalizado uma busca com range de data por início e fim; valem as observações para a US 23.

+

Decisões

+

Será validado pelo time a viabilidade de inserir um gráfico de pizza na view da US 22; +As US’s 23 e 24 serão unificadas, diferenciando-se apenas pela regra de negócio do perfil de usuários: gestor e sindicalizado. +Foram apresentadas as US’s 02 e 19. Após o deploy, o PO irá verificar e fazer os testes de aceitação.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Guilherme, Anna e Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint4/pareamentos4/index.html b/ritos/sprints/sprint4/pareamentos4/index.html new file mode 100644 index 0000000..7f25532 --- /dev/null +++ b/ritos/sprints/sprint4/pareamentos4/index.html @@ -0,0 +1,2282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pareamentos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Pareamentos

+

Na Sprint 4, foram definidos dois pareamentos. Nessa Sprint, ficou definido um novo padrão de pareamentos, conforme notou-se necessário no fluxo de trabalho das semanas anteriores. As US portanto contarão sempre com dois MDS acompanhados de um EPS. Foram puxadas para o Sprint Backlog duas histórias de usuário, para que os outros estudantes pudessem finalizar suas US em andamento e EPS se encarregassem de auxiliar nas US necessárias e no aumento da cobertura de testes das US anteriores. As alocações podem ser observadas nas tabelas abaixo:

+ + + + + + + + + + + + + + + + + + + + +
PareamentoUSDescrição
Guilherme, João Victor e VictorUS16Visualizar dashboard sobre sindicalizados
Davi Nobre, Davi Mesquita e IngridUS20Cadastrar movimentações financeiras
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento06/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint4/planning4/index.html b/ritos/sprints/sprint4/planning4/index.html new file mode 100644 index 0000000..6e092f0 --- /dev/null +++ b/ritos/sprints/sprint4/planning4/index.html @@ -0,0 +1,2339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 4

+

Planning

+

Data: 05/08/24

+

Objetivos da Sprint Planning

+

Para a Sprint 4, foram selecionadas histórias de usuário do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribuídas duas novas histórias de usuário conforme os pareamentos definidos.

+

Estrutura da Sprint Planning

+

As histórias de usuário definidas pro sprint backlog foram:

+
    +
  • US16 - Visualizar dashboard de informações dos sindicalizados
  • +
  • US20 - Cadastrar movimentações financeiras
  • +
+

Os critérios de aceitação e protótipos das duas US ficam para validação de forma assíncrona e foram definidos os pareamentos responsáveis por cada uma.

+

Além dos critérios de aceitação e protótipos, foram definidos os pontos por história de cada US, utilizando uma ferramenta online para o Planning Poker.

+

Algumas US da Sprint 3 seguiram sendo finalizadas nos dias seguintes, como foco. As US puxadas para o Backlog da Sprint 4 devem ser iniciadas conforme as US da Sprint 3 forem finalizadas.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento16/08/24Guilherme, Anna e Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint4/retrospectiva/index.html b/ritos/sprints/sprint4/retrospectiva/index.html new file mode 100644 index 0000000..df21a95 --- /dev/null +++ b/ritos/sprints/sprint4/retrospectiva/index.html @@ -0,0 +1,2282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retro - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva 09/08

+

Pontos positivos e negativos

+

retro0908

+

Coisas boas: apoio dos EPS, ritmo de trabalho dos MDS e uma reunião de alinhamento realizada entre aulas com o time.

+

Coisas ruins: dificuldade de comunicação com cliente, atraso de validações e volume de trabalho.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint4/review4/index.html b/ritos/sprints/sprint4/review4/index.html new file mode 100644 index 0000000..073968d --- /dev/null +++ b/ritos/sprints/sprint4/review4/index.html @@ -0,0 +1,2401 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Review

+ +

Review

+

Data: 12/08/24 +Facilitador: Alvaro
+Responsáveis pela ata: Anna e Guilherme

+

Participantes:

+
    +
  • Alvaro Henrique de Sousa Gouveaa
  • +
  • Anna Clara Cardoso Evangelista
  • +
  • Davi Dos Santos Brito
  • +
  • Diogo Rodrigues Barboza
  • +
  • Guilherme Storch De Oliveira
  • +
  • Ingrid da Silva Carvalho
  • +
  • João Victor Carvalho Nobre
  • +
  • Jose Eduardo Vieira Do Prado
  • +
  • Milena Fernandes Rocha
  • +
  • Sara Paula Lima Campos
  • +
  • Matheus Amaral
  • +
+

Pauta:

+

Alinhamento sobre o roadmap do projeto; +Validação dos protótipos das US’s: 21, 22, 23, 24. +Validação das Us’s para a próxima release: 19, 02,

+

Observações

+

Foram validadas as US’s 21, 22, 23, com algumas ressalvas em seus respectivos protótipos; +A US 21 - gerar relatório financeiro - Não possui critérios de aceitação claros; foi alinhado com o P.O. a respeito das sua especificidade. Será feito um ajuste no protótipo para futura validação; +Na US 22 - acessar prestação de contas do sindicato, o P.O. sugeriu inserir na view do sindicalizado uma label com o valor gasto para cada movimentação do sindicato, bem como um filtro de pesquisa de cada um dos valores gastos pelo sindicato. Serão trocadas as labels “Saldo inicial” e “Saldo final” para “entrada” e “saída”. Será feito um ajuste no protótipo para futura validação; +Na US 23 - Consulta do histórico de contribuição do sindicalizado, o P.O. sugeriu inserir na view uma label com o valor gasto para cada contribuição do sindicalizado, bem como o valor total no intervalo selecionado na filtragem. Existem 4 tipos de contribuição. Será feito um ajuste no protótipo para futura validação; +Na US 24 - Acessar histórico de contribuição como sindicalizado, o P.O. sugeriu inserir na view do sindicalizado uma busca com range de data por início e fim; valem as observações para a US 23.

+

Decisões

+

Será validado pelo time a viabilidade de inserir um gráfico de pizza na view da US 22; +As US’s 23 e 24 serão unificadas, diferenciando-se apenas pela regra de negócio do perfil de usuários: gestor e sindicalizado. +Foram apresentadas as US’s 02 e 19. Após o deploy, o PO irá verificar e fazer os testes de aceitação.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento16/08/24Guilherme, Anna e Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint5/pareamentos5/index.html b/ritos/sprints/sprint5/pareamentos5/index.html new file mode 100644 index 0000000..5254c5f --- /dev/null +++ b/ritos/sprints/sprint5/pareamentos5/index.html @@ -0,0 +1,2302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pareamentos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Pareamentos

+

Na Sprint 5, as atividades foram separadas de forma a aliviar o gargalo de atividades que estavam nas suas fases finais (testes unitários e/ou testes de aceitação). Além disso, as US16 e US20 da Sprint 4 continuaram em progresso.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PareamentoUSDescrição
Sara CamposUS19Revisão e testes unitários de Cadastro de benefícios
Davi Nobre e José EduardoUS17Testes unitários de Cadastro de perfis
Davi Mesquita e DiogoUS03Testes unitários de Cadastro de fornecedores
MilenaUS05Testes unitários de Cadastro de contas bancárias
Guilherme, João Victor e Victor YukioUS16Visualizar dashboard sobre sindicalizados
Davi Nobre, Davi Mesquita e IngridUS20Cadastrar movimentações financeiras
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint5/planning5/index.html b/ritos/sprints/sprint5/planning5/index.html new file mode 100644 index 0000000..78850cf --- /dev/null +++ b/ritos/sprints/sprint5/planning5/index.html @@ -0,0 +1,2312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 5

+

Planning/Review

+

Data: 12/08/24

+

Objetivos da Sprint Planning

+

Para a Sprint 5, ficou definido que não seriam iniciadas mais US, enquanto as US em andamento, em testes ou em aceitação ainda não estivessem finalizadas. Dessa forma, foi realizado um Dojo de Testes para aumentar o volume de pessoas trabalhando em finalizar todas as histórias de usuário. Como as US16 e US20 da Sprint 4 continuaram em andamento, os integrantes que não estavam nesses pareamentos da Sprint 4, foram divididos para aumentar a cobertura de testes das US que já estavam revisadas ou em testes de aceitação com usuário. Assim, foram definidos os pareamentos dessa sprint.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento16/08/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint5/retrospectiva/index.html b/ritos/sprints/sprint5/retrospectiva/index.html new file mode 100644 index 0000000..2bdb447 --- /dev/null +++ b/ritos/sprints/sprint5/retrospectiva/index.html @@ -0,0 +1,2282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retro - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva 12/08

+

Pontos positivos e negativos

+

retro1208

+

Coisas boas: apoio dos EPS, ritmo de trabalho dos MDS, integração do time e US validadas.

+

Coisas ruins: pressão da reta final.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint5/review5/index.html b/ritos/sprints/sprint5/review5/index.html new file mode 100644 index 0000000..7267252 --- /dev/null +++ b/ritos/sprints/sprint5/review5/index.html @@ -0,0 +1,2396 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Review

+ +

Review

+

Data: 19/08/24
+Facilitador: Ingrid
+Responsáveis pela ata: João Victor e Davi Nobre

+

Participantes:

+
    +
  • Alvaro Henrique de Sousa Gouveaa
  • +
  • Anna Clara Cardoso Evangelista
  • +
  • Davi Dos Santos Brito
  • +
  • Diogo Rodrigues Barboza
  • +
  • Guilherme Storch De Oliveira
  • +
  • Ingrid da Silva Carvalho
  • +
  • João Victor Carvalho Nobre
  • +
  • Jose Eduardo Vieira Do Prado
  • +
  • Milena Fernandes Rocha
  • +
  • Sara Paula Lima Campos
  • +
  • Matheus Amaral
  • +
  • Davi Mendonça
  • +
+

Pauta:

+

Alinhamento sobre os retornos dos testes de aceitação;
+Atualização das US em andamento;
+Preparação para release MVP.

+

Observações

+

Nessa reunião foram esclarecidas dúvidas originadas da US16, por exemplo, Sexo era um campo não obrigatório, o que afetaria nas estatísitcas coletadas para o dashboard. Outro problema, era a lotação ser um campo livre, que dificultava a visualização dos sindicalizados entre lotações. Foi falado também sobre limpar a visualização dos HUBS.

+

Decisões

+

Foram encaminhadas as alterações, de forma a deixar apenas botões de lista nos HUBS, visto que o cadastro pode ser acessado via lista. Além disso, surgiu uma nova história de usuário que foi priorizada para a Release MVP, na qual haveria um cadastro de órgão e, dentro do órgão, pudessem ser cadastradas as lotações que ficariam disponíveis para preenchimento no formulário de filiação.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24João Victor, Davi Nobre e Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint6/pareamentos6/index.html b/ritos/sprints/sprint6/pareamentos6/index.html new file mode 100644 index 0000000..994edff --- /dev/null +++ b/ritos/sprints/sprint6/pareamentos6/index.html @@ -0,0 +1,2287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pareamentos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Pareamentos

+

Na Sprint 6, as atividades foram separadas de forma a entregar as atividades previstas para o MVP. Destas, a US21 e a US22 foram remanejadas e jogadas para sprint futura, a fim de finalizar com qualidade as US que já estavam priorizadas em andamento.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
PareamentoUSDescrição
José Eduardo, Davi Nobre e IngridUS23Consulta do histórico de contribuição do sindicalizado
Diogo, Milena e SaraUS35Cadastro de órgão lotação
AnnaUS20Testes
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint6/planning6/index.html b/ritos/sprints/sprint6/planning6/index.html new file mode 100644 index 0000000..c213881 --- /dev/null +++ b/ritos/sprints/sprint6/planning6/index.html @@ -0,0 +1,2339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 6

+

Planning

+

Data: 19/08/24

+

Objetivos da Sprint Planning

+

Para a Sprint 6, foram selecionadas histórias de usuário do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribuídas duas novas histórias de usuário conforme os pareamentos definidos. Nessa sprint, foi adicionada uma nova história de usuário ao Backlog do Produto, conforme necessidade identificada. Isso ocorreu por conta da US16, que diz respeito ao dashboard de estatíticas sobre os sindicalizados, na qual notou-se que seria necessário haver um cadastro de órgãos e lotações (instanciado na US35) para serem usados no cadastro de sindicalizado.

+

Estrutura da Sprint Planning

+

As histórias de usuário definidas pro sprint backlog foram:

+
    +
  • US23 - Consulta do histórico de contribuição do sindicalizado
  • +
  • US35 - Cadastrar órgãos
  • +
+

Os critérios de aceitação e protótipos já haviam sido validados anteriormente, exceto pela US35, que foi instanciada e ficou para validação de forma assíncrona.

+

Além dos critérios de aceitação e protótipos, foram definidos os pontos por história de cada US, utilizando uma ferramenta online para o Planning Poker.

+

Algumas US da Sprint 5 seguiram sendo finalizadas nos dias seguintes, com foco na entrega da Release MVP.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint6/review6/index.html b/ritos/sprints/sprint6/review6/index.html new file mode 100644 index 0000000..f987de9 --- /dev/null +++ b/ritos/sprints/sprint6/review6/index.html @@ -0,0 +1,2344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Review

+ +

Review/Apresentação da Release MVP

+

Data: 26/08/24

+

Participantes:

+
    +
  • Alvaro Henrique de Sousa Gouveaa
  • +
  • Anna Clara Cardoso Evangelista
  • +
  • Davi Dos Santos Brito
  • +
  • Davi Mesquita
  • +
  • Diogo Rodrigues Barboza
  • +
  • Guilherme Storch De Oliveira
  • +
  • Ingrid da Silva Carvalho
  • +
  • João Victor Carvalho Nobre
  • +
  • Jose Eduardo Vieira Do Prado
  • +
  • Milena Fernandes Rocha
  • +
  • Sara Paula Lima Campos
  • +
  • Victor Yukio
  • +
  • Matheus Amaral
  • +
  • Davi Mendonça
  • +
+

Pauta:

+

Apresentação das US do MVP; +Atualização do documento de custos; +Atualização do andamento do roadmap.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint7/pareamentos7/index.html b/ritos/sprints/sprint7/pareamentos7/index.html new file mode 100644 index 0000000..aabcb85 --- /dev/null +++ b/ritos/sprints/sprint7/pareamentos7/index.html @@ -0,0 +1,2297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pareamentos - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Pareamentos

+

Na Sprint 7, as atividades foram separadas de forma a corrigir as US do MVP para entrega da Release N. Além disso, foi puxada a US21 do backlog do produto.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PareamentoUSDescrição
José Eduardo, Davi Nobre e SaraUS21Gerar relatório de movimentações financeiras
Diogo e João VictorUS17Cadastrar perfis
Diogo e João VictorUS18Atribuir perfis
Milena e GuilhermeENH-US02Evolução adaptativa da US02
Milena e GuilhermeENH-US05Evolução corretiva da US05
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint7/planning7/index.html b/ritos/sprints/sprint7/planning7/index.html new file mode 100644 index 0000000..4fdec91 --- /dev/null +++ b/ritos/sprints/sprint7/planning7/index.html @@ -0,0 +1,2339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 7

+

Planning

+

Data: 26/08/24

+

Objetivos da Sprint Planning

+

Para a Sprint 7, foram selecionadas histórias de usuário do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribuídas histórias de usuário conforme os pareamentos definidos. Além disso, nessa sprint foram iniciadas evoluções adaptativa e corretiva. Foi identificado que a US17 estava com critérios de aceitação incompletos, e a US18, que havia sido colocada na coluna Icebox do Zenhub, foi repriorizada e puxada para o sprint backlog.

+

Estrutura da Sprint Planning

+

As histórias de usuário definidas pro sprint backlog foram:

+
    +
  • US21 - Gerar relatório de movimentações financeiras
  • +
  • US17 - Cadastrar perfis
  • +
  • US18 - Atribuir perfis aos usuários
  • +
  • ENH-US02 - Evolução adaptativa da US02
  • +
  • ENH-US05 - Evolução corretiva da US05
  • +
+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint7/retrospectiva/index.html b/ritos/sprints/sprint7/retrospectiva/index.html new file mode 100644 index 0000000..58d8738 --- /dev/null +++ b/ritos/sprints/sprint7/retrospectiva/index.html @@ -0,0 +1,2282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retro - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva 30/08

+

Pontos positivos e negativos

+

retro3008

+

Coisas boas: entrega do MVP, apoio dos EPS, boa cobertura de testes e a chegada da reta final.

+

Coisas ruins: cansaço, dificuldade com CSS e problemas com husky.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint7/review7/index.html b/ritos/sprints/sprint7/review7/index.html new file mode 100644 index 0000000..19c8290 --- /dev/null +++ b/ritos/sprints/sprint7/review7/index.html @@ -0,0 +1,2404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Review

+ +

Review

+

Data: 02/09/24
+Facilitador: Sara

+

Participantes:

+
    +
  • Alvaro Henrique de Sousa Gouveaa
  • +
  • Anna Clara Cardoso Evangelista
  • +
  • Davi Dos Santos Brito
  • +
  • Davi Mesquita
  • +
  • Diogo Rodrigues Barboza
  • +
  • Guilherme Storch De Oliveira
  • +
  • Ingrid da Silva Carvalho
  • +
  • João Victor Carvalho Nobre
  • +
  • Jose Eduardo Vieira Do Prado
  • +
  • Milena Fernandes Rocha
  • +
  • Sara Paula Lima Campos
  • +
  • Matheus Amaral
  • +
  • Davi Mendonça
  • +
+

Pauta:

+

Apresentação das atividades em andamento e alinhamento com os POs; +Conversa sobre os próximos passos ate a release N; +Apresentação do agile evm.

+

Observações

+

Foi apontado que é necessário rever a US de login de validação do email, Matheus já aceitou porém apenas com o vídeo. +US20 - Protótipo e critério estavam um pouco confuso , campos de aceitação campo de data na listagem dd/mm/yyy e drop down na hora da edição de “tipo documento”
+US23 - observação na us de conciliação de movimentações +Colocar um botão para o admin ver o perfil
+US03 - css
+olhar para campos uf de todas as telas principalmente de fornecedores +resolver órgão e lotação
+US34 - email
+US21 e requisitos, validar csv e pdf- selecionar os campos (filtros) que ele quer, colocar brasão do sindicato

+

Decisões

+

Foram seguidas as correções pedidas e feito o protótipo da US21 que ainda não havia sido validado. Além disso, a US22 foi despriorizada num acordo entre o time e os P.Os, a fim de priorizar a entrega de qualidade das US que já estavam encaminhadas.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint8/planning8/index.html b/ritos/sprints/sprint8/planning8/index.html new file mode 100644 index 0000000..da61a0b --- /dev/null +++ b/ritos/sprints/sprint8/planning8/index.html @@ -0,0 +1,2312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Sprint 7

+

Planning

+

Data: 02/09/24

+

Objetivos da Sprint Planning

+

Para a Sprint 8, as US apenas foram contiuadas pelos seus responsáveis definidos nos pareamentos, com foco em finalizar uma entrega de qualidade para a Release N.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/sprints/sprint8/retrospectiva/index.html b/ritos/sprints/sprint8/retrospectiva/index.html new file mode 100644 index 0000000..3ba298d --- /dev/null +++ b/ritos/sprints/sprint8/retrospectiva/index.html @@ -0,0 +1,2282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Retro - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Retrospectiva da Release Final

+

Pontos positivos e negativos

+

retro0809

+

Coisas boas: entregas finalizadas, apoio dos EPS, trabalho dos MDS, evolução pessoal, pareamentos presenciais e reconhecimento do professor.

+

Coisas ruins: cansaço, bugs, tempo curto para apresentar a quantidade de coisas que foram feitas.

+

Histórico de versão

+ + + + + + + + + + + + + + + +
AlteraçãoDataAutor
Criação do documento08/09/24Sara Campos
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/template/planning/index.html b/ritos/template/planning/index.html new file mode 100644 index 0000000..a084716 --- /dev/null +++ b/ritos/template/planning/index.html @@ -0,0 +1,2221 @@ + + + + + + + + + + + + + + + + + + + + + Template Sprint Planning - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Template Sprint Planning

+

Planejamento Sprint X

+

Objetivos da sprint

+
    +
  • Objetivos da sprint
  • +
+

Tamanho da Sprint

+
    +
  • Início: -/-/2024
  • +
  • Término: -/-/2024
  • +
  • Duração: - dias
  • +
+

Pareamentos

+
    +
  • Documentar como foram escolhidos os pareamentos da sprint
  • +
  • Duplas escolhidas
  • +
+

Sprint Backlog

+
    +
  • Tabela de issues escolhidas para a semana, pontuação e responsaveis
  • +
+


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IssuePontosResponsáveis
Nome da issue-
Nome da issue-
Nome da issue-
Nome da issue-
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/template/retrospec/index.html b/ritos/template/retrospec/index.html new file mode 100644 index 0000000..950cd64 --- /dev/null +++ b/ritos/template/retrospec/index.html @@ -0,0 +1,2174 @@ + + + + + + + + + + + + + + + + + + + + + Template Retrospectiva de Sprint - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Template Retrospectiva de Sprint

+

Análise da sprint

+
    +
  • Fazer uma breve análise sobre os resultados obtidos ao fim da sprint
  • +
+

Pontos Positivos e Negativos

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/ritos/template/review/index.html b/ritos/template/review/index.html new file mode 100644 index 0000000..335f48c --- /dev/null +++ b/ritos/template/review/index.html @@ -0,0 +1,2276 @@ + + + + + + + + + + + + + + + + + + + + + Template Sprint Review - 2024.1 - SENTINELA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Template Sprint Review

+

Resultados obtidos na sprint

+

Resultados obtidos na sprint.

+

Reports

+

Tarefas Realizadas

+

Quadro que mostra quais tarefas planejadas foram concluídas.

+ + + + + + + + + + + + + + + + + + + + +
TarefaPontuaçãoConcluída
Tarefa concuída--
Tarefa não concluída--
+


+

Burndown

+
    +
  • Gráfico de Burndown da sprint(imagem)
  • +
+

Velocity

+
    +
  • Gráfico de Velocity da sprint(imagem)
  • +
+

Conhecimento dos membros

+
    +
  • Tabela de conhecimento da sprint(imagem).
  • +
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..5a7e083 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Sentinela 2024.1","text":"

Este \u00e9 o reposit\u00f3rio de documenta\u00e7\u00e3o do projeto Sentinela realizado pelos alunos das disciplinas de EPS e MDS para o SINDPOL-DF no primeiro semestre de 2024.

"},{"location":"#repositorios-do-projeto","title":"Reposit\u00f3rios do projeto","text":"
  • Documenta\u00e7\u00e3o
  • Frontend
  • Backend-Usu\u00e1rios
  • Backend-Benef\u00edcios
  • Backend-Financeiro
"},{"location":"#integrantes-do-time","title":"Integrantes do time","text":""},{"location":"#eps","title":"EPS","text":"Nome Matr\u00edcula Usu\u00e1rio Github Sara Campos 170045269 @saracampss Alvaro Gouvea 180012002 @algouvea Ingrid Carvalho 190029731 @ingridscarvalho Victor Yukio 180068229 @yukioz"},{"location":"#mds","title":"MDS","text":"Nome Matr\u00edcula Usu\u00e1rio Github Anna Brand\u00e3o 222006534 @annacbrandao Diogo Barboza 222006660 @Diogo-Barboza Davi Mesquita 222006650 @davimesquit Davi Nobre 211062929 @jagaima Guilherme Storch 211030765 @storch7 Milena Rocha 222022000 @milenafrocha Jo\u00e3o Victor Nobre 202017423 @Gam13 Jos\u00e9 Eduardo 221008202 @jevprado"},{"location":"#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 26/03/24 Sara Campos Corre\u00e7\u00f5es 28/03/24 Sara Campos Atualiza\u00e7\u00e3o dos reposit\u00f3rios do projeto 18/07/24 Sara Campos"},{"location":"conclusao/","title":"Conclus\u00e3o do projeto","text":""},{"location":"conclusao/#pessoas","title":"Pessoas","text":"

O gerenciamento de pessoas pode ser observado na aba Alinhamento desta Wiki, onde tem-se os canais que foram utilizados, dojos realizados e informa\u00e7\u00f5es sobre disponibilidade e evolu\u00e7\u00e3o de conhecimento dos estudantes.

Os canais de comunica\u00e7\u00e3o foram considerados satisfat\u00f3rios, visto que, auxiliaram devidamente as atividades executadas na disciplina. Os treinamentos/dojos planejados foram todos realizados em tempo h\u00e1bil para que os MDS fossem capacitados e pudessem contribuir no projeto.

Quanto \u00e0 disponibilidade dos membros, antes do per\u00edodo de greve havia bastante dificuldade de encontrar hor\u00e1rios em que um qu\u00f3rum m\u00ednimo de pessoas estivesse dispon\u00edvel. No entanto, ap\u00f3s o per\u00edodo de greve, como algumas mat\u00e9rias foram finalizadas, os integrantes ficaram com mais hor\u00e1rios livres. Assim, foram atualizados os dados na planilha e essa melhoria refletiu na \u00f3tima comunica\u00e7\u00e3o da equipe, que permitiu realizar todos os rituais com participa\u00e7\u00e3o significativa e reuni\u00f5es extraordin\u00e1rias conforme necess\u00e1rio.

Por fim, o quadro de conhecimento foi criado conforme os conhecimentos iniciais dos estudantes e atualizado a cada sprint realizada. \u00c9 poss\u00edvel observar que o mapa de calor evolui de majoritariamente composto por cores quentes para majoritariamente composto por cores frias, o que representa uma not\u00e1vel e satisfat\u00f3ria curva de conhecimento de todos do time.

"},{"location":"conclusao/#escopo-custo-e-tempo","title":"Escopo, custo e tempo","text":"

O escopo definido para esse projeto comportava todas as hist\u00f3rias do MVP e suas poss\u00edveis melhorias e corre\u00e7\u00f5es. Inicialmente, o cronograma previa a entrega de todas as US do MVP na Release do dia 26/08, entretanto, finaliza-se o tempo estipulado da disciplina com o escopo do MVP apenas parcialmente finalizado. Das 16 hist\u00f3rias instanciadas no Backlog (15 planejadas e 1 adicionada), foi poss\u00edvel entregar 14, al\u00e9m de 2 melhorias.

Quanto ao custo, \u00e9 poss\u00edvel observar por meio dos documentos de Custo e Agile EVM que, com a varia\u00e7\u00e3o do escopo no tempo definido pelo cronograma, o valor agregado acabou n\u00e3o alcan\u00e7ando o valor planejado.

"},{"location":"conclusao/#risco","title":"Risco","text":"

Os riscos do projeto foram monitorados a cada semana, de forma que, \u00e9 poss\u00edvel observar no comportamento do gr\u00e1fico de riscos ao longo do projeto que foi realizado um bom gerenciamento.

Boa parte dos riscos identificados foram eliminados ou mitigados, possibilitando uma entrega de qualidade e com grande volume de funcionalidades.

"},{"location":"conclusao/#qualidade","title":"Qualidade","text":"

O projeto conta com m\u00e9tricas consideradas pelo time como razoavelmente boas. As medidas que n\u00e3o passam pelos valores de refer\u00eancia em alguns reposit\u00f3rios s\u00e3o cobertura, seguran\u00e7a e duplica\u00e7\u00f5es.

A cobertura alcan\u00e7ada, no entanto, \u00e9 >80% no backend de Financeiro (considerado pelo time como o que mais precisa dessa confiabilidade) e >78% nos backends de Benef\u00edcios e Usu\u00e1rios e no frontend. O time considera essas medidas adequadas ao projeto.

Quanto \u00e0 seguran\u00e7a, apenas um reposit\u00f3rio falha nesse quesito, o backend de Benef\u00edcios. Este foi o reposit\u00f3rio menos abordado no escopo definido para este semestre, no qual apenas uma US foi desenvolvida, o que indica que ainda h\u00e1 bastante espa\u00e7o para melhorias em trabalhos futuros.

Por fim, as duplica\u00e7\u00f5es s\u00e3o 0% em todos os backends, mas o frontend alcan\u00e7a um valor >5%. Isto se d\u00e1, provavelmente, pela falha do time em componentizar e modularizar adequadamente o c\u00f3digo fonte. Essa \u00e9 uma melhoria que pode ser executada futuramente com uma simples revis\u00e3o e refatoramento de partes do c\u00f3digo que apresentem duplica\u00e7\u00f5es.

"},{"location":"conclusao/#consideracoes-finais","title":"Considera\u00e7\u00f5es finais","text":""},{"location":"conclusao/#historico-de-versoes","title":"Hist\u00f3rico de Vers\u00f5es","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Ingrid Carvalho e Sara Campos"},{"location":"alinhamento/canais/","title":"Canais de comunica\u00e7\u00e3o","text":"

Para manter o time alinhado foram escolhidos alguns canais de comunica\u00e7\u00e3o para reuni\u00f5es, discuss\u00f5es r\u00e1pidas, organiza\u00e7\u00e3o de atividades e gerenciamento do projeto.

"},{"location":"alinhamento/canais/#plataformas-escolhidas","title":"Plataformas escolhidas","text":"
  • Telegram: usado para comunica\u00e7\u00e3o r\u00e1pida da equipe e passagem de informa\u00e7\u00f5es rotineiras.

  • Microsoft Teams: usado para reuni\u00f5es com cliente, bem como para realizar e gravar treinamentos realizados com os MDS (DOJO).

  • Zenhub: usado para criar e compartilhar o quadro kanban da equipe.

  • Discord: usado para pareamentos e reuni\u00f5es do time que n\u00e3o precisam ser gravadas.

  • Github: usado para reposit\u00f3rios de documenta\u00e7\u00e3o e issues assim como reposit\u00f3rios de c\u00f3digo fonte.

  • Google Drive: usado para salvar e compartilhar arquivos.

"},{"location":"alinhamento/canais/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 27/03/24 Sara Campos"},{"location":"alinhamento/disponibilidade/","title":"Quadro de disponibilidade","text":"

Para facilitar o agendamento de reuni\u00f5es do time foi criada uma planilha de disponibilidade. Cada um preencheu a planilha com hor\u00e1rios em que os integrantes estavam livres e os hor\u00e1rios dispon\u00edveis com agendamento pr\u00e9vio, por\u00e9m com a quantidade de pessoas na equipe foi dif\u00edcil encontrar hor\u00e1rios em que todos estivessem livres. Dessa forma, foi definido um qu\u00f3rum m\u00ednimo de reuni\u00e3o de 8 pessoas (garantindo um m\u00ednimo de metade dos MDS presentes).

"},{"location":"alinhamento/disponibilidade/#horarios-de-reunioes","title":"Hor\u00e1rios de reuni\u00f5es","text":"Reuni\u00e3o Hor\u00e1rio Modelo Reuni\u00e3o com cliente Toda segunda \u00e0s 20h Remoto Dojo Esporadicamente conforme agendamento Remoto/Presencial"},{"location":"alinhamento/disponibilidade/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 27/03/24 Sara Campos Corre\u00e7\u00f5es 28/03/24 Sara Campos Atualiza\u00e7\u00e3o 03/08/24 Sara Campos"},{"location":"alinhamento/dojos/","title":"Dojo","text":"

Os dojos s\u00e3o treinamentos realizados pelos EPS para contribuir com a evolu\u00e7\u00e3o do conhecimento t\u00e9cnico dos MDS ao longo da disciplina. Conforme as tecnologias usadas neste projeto e a demanda de treinamento, os dojos devem ser agendados. Abaixo segue a lista de treinamentos j\u00e1 realizados pela equipe. Nas issues do nosso Github podem ser encontrados mais detalhes sobre cada um dos dojos.

T\u00f3pico Data Hor\u00e1rio Respons\u00e1vel Modelo Git 27/03/24 21h Victor Yukio Remoto Scrum + Kanban 04/04/24 13h Sara Campos Presencial + Remoto HTML + CSS + Material UI + Princ\u00edpios de ReactJS 06/04/24 15h Victor Yukio Remoto Frontend Vite.js 11/07/24 20h Sara Campos, Ingrid Carvalho e Victor Yukio Remoto Backend Node Express 16/07/24 20h Victor Yukio Remoto Figma 20/07/24 9h Sara Campos Remoto Testes unit\u00e1rios com Vitest e Jest 14/08/24 20h30 Sara Campos e Victor Yukio Remoto"},{"location":"alinhamento/dojos/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 27/03/24 Sara Campos Atualiza\u00e7\u00e3o 05/04/24 Sara Campos Atualiza\u00e7\u00e3o 06/04/24 Sara Campos Atualiza\u00e7\u00e3o 18/07/24 Sara Campos Atualiza\u00e7\u00e3o 20/07/24 Sara Campos Atualiza\u00e7\u00e3o 16/08/24 Sara Campos"},{"location":"alinhamento/heatmap/","title":"Quadro de conhecimento","text":"

Para entender de onde cada integrante est\u00e1 partindo em termos de conhecimento sobre as tecnologias usadas e monitorar a evolu\u00e7\u00e3o de cada um ao longo da disciplina foi criado um quadro de conhecimento. A equipe preencheu o quadro conforme uma autoavalia\u00e7\u00e3o do seu n\u00edvel de conhecimento t\u00e9cnico. Esse quadro ajuda a avaliar demanda de dojos para os MDS, assim como ajuda a formar bons pareamentos conforme as habilidades de cada pessoa do time.

"},{"location":"alinhamento/heatmap/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 27/03/24 Sara Campos Atualiza\u00e7\u00e3o 03/08/24 Sara Campos"},{"location":"gestao/arquitetura/","title":"Arquitetura de Software","text":""},{"location":"gestao/arquitetura/#visao-geral","title":"Vis\u00e3o Geral","text":"

A arquitetura deste sistema \u00e9 composta por uma interface central que se comunica com tr\u00eas microsservi\u00e7os distintos: Usu\u00e1rios, Financeiro e Benef\u00edcios.

Os microsservi\u00e7os s\u00e3o respons\u00e1veis por \u00e1reas funcionais espec\u00edficas e se comunicam de forma ass\u00edncrona e segura atrav\u00e9s de APIs. Cada microsservi\u00e7o exp\u00f5e uma interface de API que permite que a interface central e os outros microsservi\u00e7os realizem opera\u00e7\u00f5es conforme necess\u00e1rio.

A separa\u00e7\u00e3o dos microsservi\u00e7os e seus bancos de dados permite a escalabilidade independente de cada componente. Altera\u00e7\u00f5es e manuten\u00e7\u00f5es em um microsservi\u00e7o n\u00e3o afetam diretamente os outros, promovendo uma arquitetura facilmente adapt\u00e1vel a mudan\u00e7as.

"},{"location":"gestao/arquitetura/#componentes-da-arquitetura","title":"Componentes da Arquitetura","text":""},{"location":"gestao/arquitetura/#1-interface","title":"1. Interface","text":"

A interface atua como o ponto de entrada para os usu\u00e1rios e sistemas externos, permitindo a intera\u00e7\u00e3o com o sistema de forma integrada. Esta camada \u00e9 respons\u00e1vel por:

  • Recep\u00e7\u00e3o de Requisi\u00e7\u00f5es: Captura e valida as requisi\u00e7\u00f5es dos usu\u00e1rios ou sistemas externos.
  • Autentica\u00e7\u00e3o e Autoriza\u00e7\u00e3o: Garante que as requisi\u00e7\u00f5es sejam realizadas por usu\u00e1rios autorizados e autenticados.
  • Orquestra\u00e7\u00e3o de Requisi\u00e7\u00f5es: Coordena as intera\u00e7\u00f5es entre os microsservi\u00e7os, garantindo que as respostas sejam consolidadas e apresentadas ao usu\u00e1rio final de forma coesa.
"},{"location":"gestao/arquitetura/#2-microsservico-de-usuarios","title":"2. Microsservi\u00e7o de Usu\u00e1rios","text":"

O microsservi\u00e7o de Usu\u00e1rios gerencia todas as opera\u00e7\u00f5es relacionadas aos usu\u00e1rios do sistema.

Banco de Dados do Usu\u00e1rios: O banco de dados associado a este microsservi\u00e7o armazena informa\u00e7\u00f5es detalhadas sobre cada usu\u00e1rio

"},{"location":"gestao/arquitetura/#3-microsservico-financeiro","title":"3. Microsservi\u00e7o Financeiro","text":"

O microsservi\u00e7o Financeiro \u00e9 respons\u00e1vel por gerenciar todas as transa\u00e7\u00f5es e opera\u00e7\u00f5es financeiras. Banco de Dados do Financeiro: O banco de dados deste microsservi\u00e7o armazena dados relacionados a fornecedores, contas e hist\u00f3ricos financeiros.

"},{"location":"gestao/arquitetura/#4-microsservico-de-beneficios","title":"4. Microsservi\u00e7o de Benef\u00edcios","text":"

O microsservi\u00e7o de Benef\u00edcios cuida da administra\u00e7\u00e3o dos benef\u00edcios/conv\u00eanios oferecidos aos sindicalizados. Banco de Dados de Benef\u00edcios: O banco de dados deste microsservi\u00e7o armazena informa\u00e7\u00f5es sobre os benef\u00edcios dispon\u00edveis.

"},{"location":"gestao/arquitetura/#tecnologias","title":"Tecnologias","text":""},{"location":"gestao/arquitetura/#1-reactvitejs","title":"1. React/ViteJS","text":"

React \u00e9 a principal biblioteca utilizada no frontend deste projeto, focada na constru\u00e7\u00e3o de interfaces de usu\u00e1rio reativas e componentizadas. Com sua abordagem baseada em componentes, o React permite um desenvolvimento modular, facilitando a reutiliza\u00e7\u00e3o de c\u00f3digo e a manuten\u00e7\u00e3o do sistema. A escolha de ViteJS como o build tool agiliza o processo de desenvolvimento, fornecendo uma experi\u00eancia de desenvolvimento mais r\u00e1pida e eficiente, com suporte nativo a ESModules e hot module replacement (HMR). Juntos, React e ViteJS proporcionam uma interface de usu\u00e1rio moderna, din\u00e2mica e altamente responsiva.

"},{"location":"gestao/arquitetura/#2-nodejs","title":"2. Node.js","text":"

Node.js \u00e9 utilizado no projeto como o ambiente de execu\u00e7\u00e3o para o backend, gra\u00e7as ao seu modelo de execu\u00e7\u00e3o ass\u00edncrono e n\u00e3o bloqueante. Essa caracter\u00edstica \u00e9 essencial para lidar com um grande n\u00famero de requisi\u00e7\u00f5es simult\u00e2neas, tornando-o ideal para a constru\u00e7\u00e3o de APIs r\u00e1pidas e escal\u00e1veis. Al\u00e9m disso, Node.js \u00e9 multiplataforma e possui uma vasta biblioteca de pacotes NPM, que facilita a integra\u00e7\u00e3o de funcionalidades adicionais no backend, promovendo agilidade no desenvolvimento e flexibilidade na escolha de tecnologias.

"},{"location":"gestao/arquitetura/#3-express","title":"3. Express","text":"

Express \u00e9 o framework Node.js escolhido para estruturar as APIs do backend, fornecendo uma camada leve e flex\u00edvel para o desenvolvimento de rotas e middleware. Sua simplicidade e desempenho eficiente permitem a cria\u00e7\u00e3o de APIs RESTful de maneira r\u00e1pida, sem sacrificar a robustez. Atrav\u00e9s do uso de middlewares, o Express facilita o gerenciamento de requisi\u00e7\u00f5es, tratamento de erros, autentica\u00e7\u00e3o e integra\u00e7\u00e3o com servi\u00e7os externos, assegurando uma comunica\u00e7\u00e3o eficaz entre o frontend e o banco de dados, bem como entre diferentes microsservi\u00e7os.

"},{"location":"gestao/arquitetura/#4-mongodb","title":"4. MongoDB","text":"

MongoDB \u00e9 empregado como o banco de dados NoSQL neste projeto, oferecendo uma solu\u00e7\u00e3o flex\u00edvel e escal\u00e1vel para o armazenamento de dados. Sua estrutura baseada em documentos JSON permite um mapeamento direto dos dados para objetos em linguagens de programa\u00e7\u00e3o, simplificando a manipula\u00e7\u00e3o de informa\u00e7\u00f5es complexas. O MongoDB \u00e9 altamente escal\u00e1vel, sendo uma escolha apropriada para aplica\u00e7\u00f5es que exigem alta disponibilidade e capacidade de crescimento din\u00e2mico dos dados, caracter\u00edsticas essenciais para atender \u00e0s demandas do projeto.

"},{"location":"gestao/arquitetura/#5-mongoose","title":"5. Mongoose","text":"

Mongoose \u00e9 a biblioteca ODM (Object Data Modeling) utilizada para gerenciar intera\u00e7\u00f5es com o MongoDB, proporcionando uma camada de abstra\u00e7\u00e3o que simplifica o mapeamento de objetos JavaScript para documentos do banco de dados. Com Mongoose, \u00e9 poss\u00edvel definir schemas rigorosos, realizar valida\u00e7\u00f5es autom\u00e1ticas e criar rela\u00e7\u00f5es complexas entre documentos. Essa tecnologia contribui para um desenvolvimento backend mais organizado e seguro, garantindo que os dados sejam consistentes e validados antes de serem armazenados no banco de dados MongoDB.

"},{"location":"gestao/arquitetura/#visao-logica","title":"Vis\u00e3o l\u00f3gica","text":""},{"location":"gestao/arquitetura/#diagrama-de-pacotes","title":"Diagrama de Pacotes","text":""},{"location":"gestao/arquitetura/#diagrama-de-pacotes-frontend","title":"Diagrama de Pacotes Frontend","text":"

Os principais componentes do diagrama s\u00e3o:

  • src: A pasta raiz do seu projeto, onde reside todo o c\u00f3digo fonte. Components: Aqui voc\u00ea encontrar\u00e1 os componentes reutiliz\u00e1veis da sua aplica\u00e7\u00e3o. Um componente React \u00e9 um peda\u00e7o de interface que pode ser renderizado independentemente e, geralmente, encapsula l\u00f3gica e estilo.

  • Pages: Nesta pasta, voc\u00ea ir\u00e1 encontrar os componentes que representam as diferentes p\u00e1ginas do seu aplicativo. Cada p\u00e1gina \u00e9, essencialmente, um grande componente que pode conter outros componentes menores.

  • Service: Essa pasta geralmente cont\u00e9m a l\u00f3gica de neg\u00f3cios da sua aplica\u00e7\u00e3o, como fun\u00e7\u00f5es para fazer requisi\u00e7\u00f5es a APIs, manipular dados, etc.

  • Context: Aqui voc\u00ea define o contexto da sua aplica\u00e7\u00e3o, uma forma de gerenciar estado global sem precisar passar props por v\u00e1rias camadas de componentes.

  • Utils: Cont\u00e9m fun\u00e7\u00f5es utilit\u00e1rias que podem ser usadas em diversas partes do seu c\u00f3digo, como fun\u00e7\u00f5es de formata\u00e7\u00e3o, valida\u00e7\u00e3o, etc.

  • Assets: Armazena arquivos est\u00e1ticos como imagens, fontes, etc.

  • App: O componente principal da sua aplica\u00e7\u00e3o, que renderiza todas as outras partes.

"},{"location":"gestao/arquitetura/#diagrama-de-pacotes-backend","title":"Diagrama de Pacotes Backend","text":"

Os principais componentes do diagrama s\u00e3o:

  • src: A pasta raiz do projeto, como no diagrama original.

  • controllers: Cont\u00e9m a l\u00f3gica de neg\u00f3cios espec\u00edfica de cada recurso (usu\u00e1rios, produtos, etc.). Cada controlador exp\u00f5e um conjunto de endpoints (rotas) que podem ser chamados por clientes. Exemplo: UserController.js poderia ter m\u00e9todos como createUser, getUserById, updateUser.

  • models: Representam as estruturas de dados do seu aplicativo, definindo os esquemas para os seus dados. Geralmente, se mapeiam para tabelas em um banco de dados.

  • utils: Cont\u00e9m fun\u00e7\u00f5es utilit\u00e1rias que podem ser usadas em diversas partes do c\u00f3digo, como enviar emails, gerar tokens, etc.

  • routes: Definem as rotas da sua aplica\u00e7\u00e3o, ou seja, os caminhos que os clientes podem acessar. Cada rota \u00e9 mapeada para um m\u00e9todo espec\u00edfico em um controlador.

  • index.js: \u00c9 o ponto de entrada da sua aplica\u00e7\u00e3o, onde voc\u00ea inicializa o servidor Express.

"},{"location":"gestao/arquitetura/#diagramas-logico-de-dados-dld","title":"Diagramas L\u00f3gico de Dados (DLD)","text":"

O Diagrama L\u00f3gico de Dados (DLD) \u00e9 uma representa\u00e7\u00e3o gr\u00e1fica que detalha a estrutura de um banco de dados. Ele mostra como as informa\u00e7\u00f5es ser\u00e3o armazenadas, quais s\u00e3o as rela\u00e7\u00f5es entre elas e como essas informa\u00e7\u00f5es ser\u00e3o organizadas para facilitar a recupera\u00e7\u00e3o e a manipula\u00e7\u00e3o dos dados. Para ilustrar o DER, dividimos entre os micro servi\u00e7os:

"},{"location":"gestao/arquitetura/#users","title":"Users","text":""},{"location":"gestao/arquitetura/#finance","title":"Finance","text":""},{"location":"gestao/arquitetura/#benfits","title":"Benfits","text":""},{"location":"gestao/arquitetura/#5-referencias-bibliograficas","title":"5. Refer\u00eancias Bibliogr\u00e1ficas","text":"

AMAZON AWS. O que s\u00e3o microsservi\u00e7os?. Dispon\u00edvel em: https://aws.amazon.com/pt/microservices/.

Geeks-for-geeks. Package Diagram | Introduction, Elements, Use Cases and Benefits. Dispon\u00edvel em: https://www.geeksforgeeks.org/package-diagram-introduction-elements-use-cases-and-benefits/

"},{"location":"gestao/arquitetura/#historico-de-versao","title":"Hist\u00f3rico de Vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 28/07/24 Sara Campos Finaliza\u00e7\u00e3o do documento 08/09/2024 Victor Yukio"},{"location":"gestao/backlog/","title":"Backlog do produto","text":"

O backlog do produto foi definido a partir do sequenciador instanciado durante o Lean Inception. Como pode ser visto abaixo, era planejado o desenvolvimento de 12 funcionalidades como o MVP.

Com o sequenciador em m\u00e3os, o time se reuniu e come\u00e7ou a detalhar todas as funcionalidades a n\u00edvel de Hist\u00f3rias de Usu\u00e1rios, que viriam a compor o Backlog do Produto. Na imagem abaixo \u00e9 poss\u00edvel ver que quinze hist\u00f3rias foram instanciadas a partir das funcionalidades do MVP.

Al\u00e9m disso, todas as outras funcionalidades de incremente foram detalhadas a n\u00edvel de US.

O Backlog do produto, composto por todas as US, foi planejado na EAP seguindo as entregas de Release 1, Release MVP e Release N esperadas na mat\u00e9ria. Com a EAP apresentada ao cliente e validada, o quadro Zenhub foi atualizado com as US e pode ser acessado pelas issues do Github, ou por meio da instala\u00e7\u00e3o de extens\u00e3o Zenhub. Al\u00e9m disso, o Roadmap foi atualizado.

A EAP, no entanto, n\u00e3o permite uma visualiza\u00e7\u00e3o do que foi entregue aos P.Os, nem de US adicionadas conforme necessidade. Abaixo segue uma tabela com as 15 US planejadas na EAP e 1 US adicionada no andamento do projeto, bem como suas respectivas situa\u00e7\u00f5es de entrega.

C\u00f3digo da US Descri\u00e7\u00e3o Aceita\u00e7\u00e3o US01 Fazer login no sistema Aceita pelo P.O Matheus em 02/09 US02 Solicitar filia\u00e7\u00e3o Aceita pelo P.O Matheus em 19/08, mas apresentou necessidade de uma melhoria no c\u00f3digo abordada na ENH-US02 US03 Cadastrar fornecedores Aceita pelo P.O Matheus em 08/09 US04 Cadastrar usu\u00e1rios Foi identificada uma necessidade de adapta\u00e7\u00e3o no c\u00f3digo e no funcionamento para que refletisse a necessidade de ter usu\u00e1rio \"gen\u00e9rico\" e usu\u00e1rio filiado, mas isso n\u00e3o foi finalizado US05 Cadastrar contas banc\u00e1rias Aceita pelo P.O Matheus em 23/08, mas apresentou necessidade de uma melhoria no c\u00f3digo abordada na ENH-US05 US33 Atualizar dados como sindicalizados Aceita pelo P.O Matheus em 10/08 US16 Dashboard de informa\u00e7\u00f5es sobre filiados Aceita pelo P.O Matheus em 31/08 US17 Cadastrar perfis Enviada para aceita\u00e7\u00e3o com corre\u00e7\u00f5es finais em 08/09 US18 Atribuir perfis Enviada para aceita\u00e7\u00e3o em 08/09 US19 Cadastrar benef\u00edcios Aceita pelo P.O Matheus em 21/08 US20 Cadastrar movimenta\u00e7\u00f5es financeiras Enviada para aceita\u00e7\u00e3o com corre\u00e7\u00f5es finais em 06/09 US21 Gerar relat\u00f3rio de financeiro Aceita pelo P.O Matheus em 09/09 US22 Acessar presta\u00e7\u00e3o de contas Com a entrada da US35 no Backlog do Produto, a US22 foi despriorizada num acordo entre time e P.Os, portanto, n\u00e3o foi entregue US23 Acessar hist\u00f3rico de contribui\u00e7\u00e3o dos sindicalizados Enviada para aceita\u00e7\u00e3o com corre\u00e7\u00f5es finais em 08/09 US34 Gerenciar filia\u00e7\u00e3o N\u00e3o aceita por conta de defeitos US35 Cadastrar \u00f3rg\u00e3os/lota\u00e7\u00f5es (adicionado ao Backlog do Produto com o projeto em andamento) Enviada para aceita\u00e7\u00e3o em 02/09

Apesar de entregues aos P.Os, algumas US apresentaram defeitos, que s\u00e3o explicitados no documento de Melhorias e defeitos.

"},{"location":"gestao/backlog/#historico-de-versoes","title":"Hist\u00f3rico de Vers\u00f5es","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos Atualiza\u00e7\u00e3o a partir do feedback do P.O (Atualiza aceita\u00e7\u00e3o de US na tabela) 09/09/24 Sara Campos"},{"location":"gestao/ci-cd/","title":"Integra\u00e7\u00e3o e deploy cont\u00ednuos","text":""},{"location":"gestao/ci-cd/#deploy-continuo","title":"Deploy cont\u00ednuo","text":"

Foram utilizadas tr\u00eas diferentes plataformas para hospedar a arquitetura do sistema. Primeiramente, foi escolhido o Netlify para a hospedagem do Frontend. A plataforma \u00e9 simples e intuitiva, al\u00e9m de permitir a conex\u00e3o com deploy cont\u00ednuo de branches espec\u00edficas, permitindo a cria\u00e7\u00e3o de um ambiente de homologa\u00e7\u00e3o das hist\u00f3rias.

Considerando a arquitetura do sistema organizada em microsservi\u00e7os foi necess\u00e1rio que o deploy de backends seguisse o mesmo formato. Al\u00e9m disso, a plataforma Render n\u00e3o permitia a hospedagem dos bancos de dados de forma gratuita. Assim, foram criadas tr\u00eas inst\u00e2ncias separadas no render, contendo cada um dos backends utilizados: Usu\u00e1rios, Financeiro e Benef\u00edcios.

Por fim, os bancos de dados foram hospedados no Mongo Atlas, permitindo maior facilidade de acesso ao banco para verificar poss\u00edveis inconsist\u00eancias sem necessidade de custos adicionais.

A conex\u00e3o entre frontend e backend foi feita pela utiliza\u00e7\u00e3o de vari\u00e1veis de ambiente facilmente configur\u00e1veis para endere\u00e7ar os endpoints necess\u00e1rios. De forma similar, foi feita a conex\u00e3o de cada um dos backends com seu respectivo banco de dados.

"},{"location":"gestao/ci-cd/#integracao-continua","title":"Integra\u00e7\u00e3o cont\u00ednua","text":"

Para a integra\u00e7\u00e3o cont\u00ednua do projeto, foi criado um pipeline de CI que executava jobs de checagem de lint, format, build, test e sonarcloud. Isto \u00e9, o workflow confere se o c\u00f3digo est\u00e1 dentro dos padr\u00f5es de formata\u00e7\u00e3o definidos, se est\u00e1 sendo buildado corretamente, se todos os testes est\u00e3o passado e se as m\u00e9tricas foram enviadas para o Sonar.

Al\u00e9m disso, foi criado um pipeline de Release, para ser rodado sempre que fosse realizado um push na main e pull requests fechados na devel e main, o qual gera arquivo JSON de m\u00e9tricas do reposit\u00f3rio toda vez que uma Release \u00e9 entregue. Esses arquivos de m\u00e9tricas foram usados posteriormente no Notebook Analytics, para criar uma visualiza\u00e7\u00e3o do andamento do projeto.

"},{"location":"gestao/ci-cd/#frontend","title":"Frontend","text":"M\u00e9trica Medida Quantidade de vezes que o pipeline de CI foi executado 439 Quantidade de vezes que o pipeline de CI falhou 125 Quantidade de vezes que o pipeline de Release foi executado 62 Quantidade de vezes que o pipeline de Release falhou 26 Quantidade de PRs abertos 69 Quantidade de PRs revisados 36 Quantidade de Releases 5"},{"location":"gestao/ci-cd/#backend-usuarios","title":"Backend Usu\u00e1rios","text":"M\u00e9trica Medida Quantidade de vezes que o pipeline de CI foi executado 103 Quantidade de vezes que o pipeline de CI falhou 24 Quantidade de vezes que o pipeline de Release foi executado 34 Quantidade de vezes que o pipeline de Release falhou 14 Quantidade de PRs abertos 37 Quantidade de PRs revisados 15 Quantidade de Releases 5"},{"location":"gestao/ci-cd/#backend-beneficios","title":"Backend Benef\u00edcios","text":"M\u00e9trica Medida Quantidade de vezes que o pipeline de CI foi executado 35 Quantidade de vezes que o pipeline de CI falhou 9 Quantidade de vezes que o pipeline de Release foi executado 12 Quantidade de vezes que o pipeline de Release falhou 2 Quantidade de PRs abertos 7 Quantidade de PRs revisados 7 Quantidade de Releases 1"},{"location":"gestao/ci-cd/#backend-financeiro","title":"Backend Financeiro","text":"M\u00e9trica Medida Quantidade de vezes que o pipeline de CI foi executado 106 Quantidade de vezes que o pipeline de CI falhou 19 Quantidade de vezes que o pipeline de Release foi executado 23 Quantidade de vezes que o pipeline de Release falhou 2 Quantidade de PRs abertos 20 Quantidade de PRs revisados 10 Quantidade de Releases 3

Com rela\u00e7\u00e3o \u00e0s falhas do pipeline de CI, estas se devem em maior parte aos flaky tests, que foram um problema enfrentado pelo time durante algumas semanas. Os testes passavam localmente e na maior parte das vezes tamb\u00e9m passava no pipeline, entretanto falhava em alguns momentos. Esse problema, no entanto, foi corrigido nas \u00faltimas semanas e n\u00e3o voltou a ser notado pelos membros. Ressalta-se que alguns pipelines tamb\u00e9m falharam por testes que estavam quebrados e problemas de formata\u00e7\u00e3o, que sempre foram encaminhados para resolu\u00e7\u00e3o at\u00e9 que n\u00e3o falhassem mais.

Quanto aos pipelines de Release, as falhas inicialmente s\u00e3o referentes a configura\u00e7\u00e3o equivocada do arquivo sonar-metrics.py, que n\u00e3o estava configurado corretamente para receber branches e tags (vers\u00f5es). Esse pipeline tamb\u00e9m sofreu altera\u00e7\u00f5es quanto \u00e0 defini\u00e7\u00e3o de quando deveria ser executado, conforme apontamento do professor.

"},{"location":"gestao/ci-cd/#historico-de-versoes","title":"Hist\u00f3rico de Vers\u00f5es","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Ingrid Carvalho, Alvaro Gouvea e Sara Campos"},{"location":"gestao/custo/","title":"Custos de projeto","text":"

Esse documento descreve os custos do desenvolvimento desse projeto, contabilizando internet, energia, os equipamentos de desenvolvimento assim como o custo por hora do aluno e do professor para a institui\u00e7\u00e3o.

"},{"location":"gestao/custo/#custo-por-aluno-da-universidade-de-brasilia","title":"Custo por aluno da Universidade de Bras\u00edlia.","text":"

O custo por aluno para esse projeto foi encontrado partindo do valor anual do aluno ajustado para a infla\u00e7\u00e3o por meio da calculadora de infla\u00e7\u00e3o do Banco Central do Brasil ajustando de per\u00edodo da publica\u00e7\u00e3o da not\u00edcia at\u00e9 o m\u00eas de junho de 2024. A partir desse valor foi contabilizado o valor semanal partindo do principio de 38 semanas de aula anuais, e por fim contabilizado uma carga hor\u00e1ria entre todas as disciplinas de aproximadamente 40 horas semanais para encontrar uma estimativa de valor hora/aluno.

Custo anual por aluno Custo semanal por aluno Valor hora/aluno Custo por aluno por semana Custo total dos alunos R$ 37.551 R$ 3.129 R$ 24,70 R$ 296,45 R$ 3.556,80"},{"location":"gestao/custo/#custo-de-equipamentos-para-equipe","title":"Custo de equipamentos para equipe.","text":"

Para calcular o valor estipulamos uma m\u00e1quina com as seguintes especifica\u00e7\u00f5es:

  • Processador Intel Core i7-1165G7
  • 8gb de mem\u00f3ria RAM
  • Armazenamento SSD 256GB

O custo desse equipamento para no m\u00eas de julho de 2024 se aproxima de R$3.500 por m\u00e1quina para cada integrante da equipe.

Pre\u00e7o da unidade do equipamento Total R$ 3.500 R$ 42.000

O custo de equipamentos para desenvolvimento foi contabilizado uma \u00fanica vez no per\u00edodo de \u00ednicio da primeira sprint de desenvolvimento do produto.

"},{"location":"gestao/custo/#custos-com-energia","title":"Custos com energia","text":"

Para esse c\u00e1lculo foi contabilizado uma m\u00e1quina de uso de aproximadamente 2kwh nas 12 horas de trabalho semanais de cada integrante. De acordo com a NeoEnergia respons\u00e1vel pelo fornecimento de energia el\u00e9trica no DF o valor do kwh est\u00e1 R$0,9944 que ser\u00e1 contabilizado para as 12 horas de trabalho semanais.

Custo Semanal por integrante Total R$ 11,93 R$ 143,19"},{"location":"gestao/custo/#custos-com-internet","title":"Custos com internet","text":"

O custo m\u00e9dio para uma banda larga de internet que possui 250 mega est\u00e1 em torno de R$ 100 reais.

Custo de internet para um integrante Custo por Semana Total por Semana R$ 100 R$ 25 R$ 300"},{"location":"gestao/custo/#total","title":"Total","text":"

Com isso, podemos pegar os valores totais de todos os os custos descritos a cima e obter o custo total por semana, para as releases major e para o projeto at\u00e9 a data atual. Al\u00e9m das semanas de desenvolvimento (sprints) tamb\u00e9m foram coontabilizados o per\u00edodo de inicia\u00e7\u00e3o do projeto a partir da data de \u00ednicio da disciplina at\u00e9 o per\u00edodo inicial da primeira sprint, descontando o per\u00edodo de 15/04/2024 \u00e0 25/06/2024 por conta da greve dos docentes.

  • Custo do Projeto at\u00e9 a data:
Alunos Equipamento Enegia Internet Total R$ 49.795,20 R$ 42.000 R$ R$ 1.837,74 R$ 3.850,00 R$ 97.482,94
  • Custo da Release 1:
Alunos Equipamento Enegia Internet Total R$ 28.454,40 R$ 42.000 R$ R$ 1.050,08 R$ 2.200,00 R$ 73.704,48
  • Custo da Release MVP:
Alunos Equipamento Enegia Internet Total R$ 14.227,20 R$ 0 R$ 525,04 R$ 1.100,00 R$ 15.852,24
  • Custo da Release N:
Alunos Equipamento Enegia Internet Total R$ 7.113,60 R$ 0 R$ 262,62 R$ 550,0 R$ 7.926,12
  • Custo Semanal do Projeto:
Alunos Enegia Internet Total por Semana R$ 3.556,80 R$ 131,26 R$ 275 R$ 3.963,06

Tabela com os valores detalhados

"},{"location":"gestao/custo/#historico-de-revisao","title":"Hist\u00f3rico de Revis\u00e3o","text":"Data Descri\u00e7\u00e3o Autor 30/07/2024 Cria\u00e7\u00e3o documento \u00c1lvaro Gouvea 30/07/2024 Corre\u00e7\u00e3o de Valor \u00c1lvaro Gouvea 06/08/2024 Corre\u00e7\u00e3o do Documento \u00c1lvaro Gouvea"},{"location":"gestao/custo/#referencias","title":"Refer\u00eancias","text":"

Custo de um aluno para a Universidade Federal, \u00faltimo acesso em 30/07/2024

Notebook Lenovo, \u00faltimo acesso em 30/07/2024

Energia el\u00e9trica: Estimado conforme amostra da companhia de energia (NeoEnergia), \u00faltimo acesso em 30/07/2024

Calculadora de Infla\u00e7\u00e3o Banco Central, \u00faltimo acesso em 06/08/2024

Custos com internet, \u00faltimo acesso em 30/07/2024

"},{"location":"gestao/eap/","title":"Estrutura Anal\u00edtica do Projeto","text":"

A Estrutura Anal\u00edtica do Projeto (EAP) \u00e9 uma representa\u00e7\u00e3o hier\u00e1rquica que divide o escopo do projeto em partes menores e mais gerenci\u00e1veis. A EAP fornece uma vis\u00e3o clara e detalhada das entregas e das fases do projeto, facilitando o planejamento, a execu\u00e7\u00e3o e o controle do projeto. A imagem abaixo descreve a EAP deste projeto, destacando suas principais entregas e componentes.

No primeiro n\u00edvel tem-se o projeto, seguido pelo n\u00edvel que representa as fases do projeto (Inicia\u00e7\u00e3o, Planejamento, Execu\u00e7\u00e3o e Encerramento), que tenta dar uma no\u00e7\u00e3o de tempo e andamento do projeto ao longo do per\u00edodo definido. No n\u00edvel abaixo, tem-se os pacotes de trabalho, ou seja, as entregas de cada fase, as quais s\u00e3o especificadas em tarefas, representadas pelos quadros em azul.

"},{"location":"gestao/eap/#historico-de-versao","title":"Hist\u00f3rico de Vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 28/07/24 Sara Campos Atualiza\u00e7\u00e3o 03/08/24 Sara Campos"},{"location":"gestao/evm/","title":"EVM - Earned Value Management","text":"

O EVM (Earned Value Management) \u00e9 uma metodologia de gerenciamento de projetos que integra cronograma, custos e escopo para monitorar o desempenho do projeto. A partir de dados planejados e reais, o EVM permite criar expectativas de resultados futuros e ajustar o andamento conforme necess\u00e1rio. Dentro do EVM, uma ferramenta fundamental \u00e9 a An\u00e1lise de Valor Agregado (EVA), uma t\u00e9cnica quantitativa que avalia o desempenho do projeto ao calcular as varia\u00e7\u00f5es no cronograma e nos custos.

Quando 20% do projeto est\u00e1 conclu\u00eddo, o desempenho atual pode ser usado para prever o futuro do projeto com uma margem de erro de aproximadamente 10%. Essa capacidade preditiva torna o EVM uma das mais eficazes ferramentas de controle de custos em projetos.

Caso exista maior interesse sobre a metodologia Agile EVM, o material referente \u00e0 ela pode ser encontrado no seguinte artigo: AgileEVM \u2013 Earned Value Management in Scrum Projects. Foi utilizada como base a tabela feita pelo grupo Ada.

"},{"location":"gestao/evm/#evm-sentinela","title":"EVM - Sentinela","text":"

O processo de monitoramento do projeto se iniciou junto \u00e0 primeira sprint de desenvolvimento, a Spritn 1. Com os custos do projto j\u00e1 relatados no documento de Custos.

O acesso \u00e0 planilha incluindo a tabela e referentes g\u00b4raficos pode ser encontrado aqui.

"},{"location":"gestao/evm/#analise-das-major-releases","title":"An\u00e1lise das Major Releases","text":"

Baseando-se nos gr\u00e1ficos gerados por sprint com suas refer\u00eancias de Valor Agregado x Valor Planejado \u00e9 poss\u00edvel tirar conclus\u00f5es sobre cada uma das major releases entregue pela equipe.

"},{"location":"gestao/evm/#release-1","title":"Release 1","text":"

A Release 1 contou com duas semanas totais de desenvolvimento, com um planejamento do valor agregado do sistema pr\u00f3ximo \u00e0 25% do total esperado. Por\u00e9m por dificuldades iniciais da equipe no processo de desenvolvimento o valor total entregue e aceito n\u00e3o alcan\u00e7ou essa meta.

"},{"location":"gestao/evm/#mvp","title":"MVP","text":"

A entrega da Release MVP consistiu em 4 semanas completas de desenvolvimento. Como pode ser verificado pelo gr\u00e1fico, as primeiras semanas de desenvolvimento n\u00e3o trouxeram nenhum valor agregado enquanto o valor planejado continuava crescendo. Quanto ao valor planejado, esse cescimento constante se dava pela utiliza\u00e7\u00e3o de metodologias \u00e1geis por parte da equipe que se baseiam na entrega cont\u00ednua de valor. J\u00e1 o comportamento do valor agregado pode ser relacionado com tanto a necessidade de reescrita e organiza\u00e7\u00e3o de crit\u00e9rios de aceita\u00e7\u00e3o e hist\u00f3rias de usu\u00e1rio, quanto \u00e0 demora por parte do cliente para valida\u00e7\u00e3o das hist\u00f3rias entregues.

"},{"location":"gestao/evm/#release-n","title":"Release N","text":"

Para a entrega final, o projeto contou com 2 sprints de desenvolvimento. O foco dessas sprints era finalizar as hist\u00f3rias de usu\u00e1rio similarmente \u00e0 conrrigir poss\u00edveis erros de funcionalidade ou compreens\u00e3o de hist\u00f3rias de usu\u00e1rio anteriores, de forma que o planejamento dessas sprints trouxe menor quantidade de pontos por sprint. Por\u00e9m por conta de avan\u00e7o na aceita\u00e7\u00e3o por parte do usu\u00e1rio tivemos maior quantidade de pontos de hist\u00f3ria fechados.

"},{"location":"gestao/evm/#analise-total","title":"An\u00e1lise Total","text":"

Assim, analisando o gr\u00e1fico total do projeto \u00e9 poss\u00edvel ver uma estagna\u00e7\u00e3o da equipe para finalizar as entregas, muito passando pelos problemas citados de erros de comunica\u00e7\u00e3o levando \u00e0 reescrita de hist\u00f3rias e crit\u00e9rios de aceita\u00e7\u00e3o, assim como a demora muitas vezes para validas as entregas j\u00e1 relizadas. Ainda assim, foi poss\u00edvel finalizar muitas das hist\u00f3rias do projeto.

"},{"location":"gestao/evm/#historico-de-revisao","title":"Hist\u00f3rico de Revis\u00e3o","text":"Data Descri\u00e7\u00e3o Autor 08/09/2024 Cria\u00e7\u00e3o do Documento \u00c1lvaro Gouvea"},{"location":"gestao/evm/#referencias","title":"Refer\u00eancias","text":"
  • AgileEVM \u2013 Earned Value Management in Scrum Projects. \u00daltimo acesso em 08/09/2024.
"},{"location":"gestao/guia-de-contribuicao/","title":"Guia de Contribui\u00e7\u00e3o","text":"

Este \u00e9 o guia de contribui\u00e7\u00e3o para o projeto 2024.1-SENTINELA. Antes de iniciar qualquer desenvolvimento que contribua para esse projeto, ler esse documento \u00e9 essencial para o entendimento das regras.

As contribui\u00e7\u00f5es podem ser iniciadas a partir das issues j\u00e1 definidas.

"},{"location":"gestao/guia-de-contribuicao/#como-contribuir","title":"Como contribuir","text":"

\u00cdndice:

  1. Como criar uma issue
  2. Como criar sua branch
  3. Regras de commits
  4. Regras de um PR
"},{"location":"gestao/guia-de-contribuicao/#politica-de-issues","title":"Politica de issues","text":"

As issues devem ser criadas no reposit\u00f3rio de documenta\u00e7\u00e3o do projeto.

As issues do projetos devem ser completas e explicativas, seguindo o template de issue do reposit\u00f3rio.

As issues devem conter:

  • Um t\u00edtulo conciso e descritivo;
  • Uma descri\u00e7\u00e3o que deve incluir uma descri\u00e7\u00e3o completa da issue e suas tarefas;
  • Em caso de Hist\u00f3ria de Usu\u00e1rio, descrever de maneira clara e detalhadas os criterios de aceita\u00e7\u00e3o, assim como adicionar o pr\u00f3titpo naveg\u00e1vel do fluxo em quest\u00e3o;
  • Ao menos um Assignee respons\u00e1vel pela issue;
  • Labels;
  • Milestone (sprint) em que a issue espera ser conclui\u00edda;
  • Estimated (pontua\u00e7\u00e3o) atribuida a issue;
"},{"location":"gestao/guia-de-contribuicao/#labels","title":"Labels","text":"

Na cria\u00e7\u00e3o de uma issue, devem ser usados os r\u00f3tulos abaixo para classifc\u00e1-la:

  • Bug: indica um problema ou comportamento inesperados
  • UX: indica que a issue \u00e9 referente a pr\u00e1ticas de User Experience
  • Treinamento: indica que a issue \u00e9 sobre treinamentos (dojos)
  • Hotfix (cor #d73a4a): indica uma corre\u00e7\u00e3o de defeitos cr\u00edticos
  • Docs (cor #0075ca): indica a aplica\u00e7\u00e3o de melhorias ou adi\u00e7\u00f5es \u00e0 documenta\u00e7\u00e3o do projeto
  • Feature (cor #094EF2): indica a introdu\u00e7\u00e3o de uma funcionalidade nova US (cor #BE71F6): indica que a issue \u00e9 uma hist\u00f3ria de usu\u00e1rio (user story)
  • Frontend (cor #56384A): Indica que est\u00e1 relacionada ao frontend da aplica\u00e7\u00e3o
  • Backend (cor #95BDC7): Indica que est\u00e1 relacionada ao backend da aplica\u00e7\u00e3o
  • Arq (cor #0D5571): indica mudan\u00e7as na arquitetura da aplica\u00e7\u00e3o ou de um de seus m\u00f3dulos ou servi\u00e7os
  • Devops (cor #9014A0): indica mudan\u00e7as na esteira de integra\u00e7\u00e3o e disponibiliza\u00e7\u00e3o cont\u00ednua
  • Analytics (cor #12477F): indica mudan\u00e7as nos analisadores est\u00e1ticos
  • Easy (cor #C5DEF5): indica que a issue tem uma dificuldade baixa
  • Medium (cor #BFD4F2): indica que a issue possui um grau m\u00e9dio de dificuldade
  • Hard (cor #D4C5F9): indica que a issue possui um alto grau de dificuldade
  • EPS #006633: indica que a issue ser\u00e1 trabalhado por alunos da disciplina de Engenharia de Produto de Software (EPS)
  • MDS (cor #0068b4): indica que a issue ser\u00e1 trabalhado por alunos da disciplina de M\u00e9todos de Desenvolvimento de Software (MDS)
"},{"location":"gestao/guia-de-contribuicao/#politica-de-branches","title":"Politica de branches","text":""},{"location":"gestao/guia-de-contribuicao/#repositorios-de-desenvolvimento","title":"Reposit\u00f3rios de desenvolvimento","text":"

Nos reposit\u00f3rios a devel \u00e9 a branch padr\u00e3o que est\u00e1 sempre atualizada. A branch main comporta as Releases lan\u00e7adas do projeto, sendo a branch mais est\u00e1vel.

"},{"location":"gestao/guia-de-contribuicao/#main","title":"main","text":"

A branch main deve ser a branch mais est\u00e1vel do projeto, que estar\u00e1 em produ\u00e7\u00e3o. Essa branch \u00e9 protegida de commits e para o desenvolvimento de novas funcionalidades, deve receber Pull Requests (PRs).

"},{"location":"gestao/guia-de-contribuicao/#development","title":"development","text":"

A branch devel deve ser a branch de desenvolvomento do projeto, que estar\u00e1 em produ\u00e7\u00e3o. Essa branch tamb\u00e9m \u00e9 protegida de commits e para o desenvolvimento de novas funcionalidades, deve receber Pull Requests assim como a main(PRs). Uma vez que todas as funcionalidades da sprint s\u00e3o testadas e mescladas na branch de desenvolvimento podemos mesclar com a branch principal, a main.

"},{"location":"gestao/guia-de-contribuicao/#novas-branches","title":"Novas branches","text":"

As branches para o desenvolvimento de novas features devem ser criadas a partir da branch devel e devem seguir o padr\u00e3o x-nome-da-issue, onde x \u00e9 o n\u00famero da issue que ser\u00e1 resolvida na branch, acompanhado pelo nome da issue.

Os Pull Requests das novas branches devem ser feitos para a branch devel.

"},{"location":"gestao/guia-de-contribuicao/#repositorio-de-documentacao","title":"Reposit\u00f3rio de documenta\u00e7\u00e3o","text":"

No reposit\u00f3rio de documenta\u00e7\u00e3o temos as branches main e gh-pages. Onde na main est\u00e1 o c\u00f3digo da p\u00e1gina de documenta\u00e7\u00e3o do github pages e na branch gh-pages est\u00e1 o site compilado e em produ\u00e7\u00e3o.

Assim como nos reposit\u00f3rios de desenvolvimento do projeto, no reposit\u00f3rio de documenta\u00e7\u00e3o a branch main est\u00e1 protegida e s\u00f3 deve aceitar modifica\u00e7\u00f5es por Pull Requests..

As novas branches, assim como nos reposit\u00f3rios de desenvolvimento devem seguir a estrutura x-nome-da-issue.

"},{"location":"gestao/guia-de-contribuicao/#politica-de-commits","title":"Politica de commits","text":"

Os commits durante o desenvolvimento do c\u00f3digo devem frequentes, descritivos e concisos.

Os commits devem ser feitos em ingl\u00eas utilizando os verbos no imperativo.

Os commits podem ser feitos utilizando o parametro -s para ter a assinatura do autor do commit. Caso o commit tenha sido feito em pareamento, deve constar no commit os co-autores.

O commit deve come\u00e7ar com [y:x] -, sendo x o n\u00famero da issue que est\u00e1 sendo desenvolvida. e y a categoria do commit (feat, fix, hotfix, ...)

Exemplos de commit:

git commit -sm \"[feat:7] - Add contributing guide\n\nCo-authored-by: Nome da dupla <emaildadupla@email.com>\"\n\ngit commit -sm \"[fix:7] - Add contributing guide\n\nCo-authored-by: Nome da dupla <emaildadupla@email.com>\"\n\ngit commit -sm \"[docs:7] - Add contributing guide\n
"},{"location":"gestao/guia-de-contribuicao/#politica-de-pull-requests","title":"Politica de pull requests","text":"

Os PRs devem ser feitos a branch devel.

Os Pull Requests devem ser feitos seguindo o template:

**Issue:** closes #X (sendo #x o link para a issue x)\n\n## Descri\u00e7\u00e3o\nDescri\u00e7\u00e3o completa do que foi feito\n\n

Onde s\u00f3 deve ser utilizado o closes antes do link da issue, caso o PR resolva completamente a issue citada.

Caso o PR seja feito em um dos reposit\u00f3rios de desenvolvimento (backend de x, forntend,...), o link para a issue do reposit\u00f3rio de documenta\u00e7\u00e3o \u00e9 feito da seguinte forma: fga-eps-mds/2024.1-SENTINELA-DOC#x, onde x \u00e9 o n\u00famero da issue. E no lugar de closes deve ser utilizado resolves.

Em casos de PRs em que ainda est\u00e3o sendo desenvolvidos, deve ser acrescentado a sigla WIP antes do t\u00edtulo do PR.

Os PRs devem conter:

  • Um t\u00edtulo conciso e descritivo;
  • Um Assignee respons\u00e1vel pelo PR;
  • Um Reviewer respons\u00e1vel pela revis\u00e3o do PR;
  • Labels significativas;
  • Uma issue associada;
  • Uma descri\u00e7\u00e3o, seguindo o template do reposit\u00f3rio, que deve incluir uma descri\u00e7\u00e3o completa do que foi feito e a issue relacionada.

Os PRs s\u00f3 ser\u00e3o aceitos ap\u00f3s passarem pelo CI estabelecido e por duas revis\u00f5es.

"},{"location":"gestao/guia-de-contribuicao/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento Victor Yukio Atualiza\u00e7\u00e3o Ingrid Revis\u00e3o e adi\u00e7\u00e3o das labels 03/08/24 Sara Campos"},{"location":"gestao/manual-de-instalacao/","title":"Manual de Instala\u00e7\u00e3o do Projeto","text":""},{"location":"gestao/manual-de-instalacao/#visao-geral","title":"Vis\u00e3o Geral","text":"

Este projeto utiliza uma arquitetura de microservi\u00e7os, composta por quatro reposit\u00f3rios:

  1. Frontend: Interface do usu\u00e1rio.
  2. Backend - Usu\u00e1rios: Servi\u00e7o respons\u00e1vel pelo gerenciamento de usu\u00e1rios.
  3. Backend - Financeiro: Servi\u00e7o respons\u00e1vel pelas opera\u00e7\u00f5es financeiras.
  4. Backend - Benef\u00edcios: Servi\u00e7o respons\u00e1vel pela gest\u00e3o de benef\u00edcios.

Todos os reposit\u00f3rios s\u00e3o dockerizados, garantindo que os servi\u00e7os possam ser facilmente configurados e executados.

"},{"location":"gestao/manual-de-instalacao/#pre-requisitos","title":"Pr\u00e9-requisitos","text":"

Antes de iniciar o processo de instala\u00e7\u00e3o, certifique-se de que os seguintes softwares estejam instalados:

  • Git
  • Docker
  • Docker Compose
"},{"location":"gestao/manual-de-instalacao/#estrutura-de-repositorios","title":"Estrutura de Reposit\u00f3rios","text":"
  • Reposit\u00f3rio do Frontend
  • Reposit\u00f3rio do Backend - Usu\u00e1rios
  • Reposit\u00f3rio do Backend - Financeiro
  • Reposit\u00f3rio do Backend - Benef\u00edcios
"},{"location":"gestao/manual-de-instalacao/#passo-a-passo-de-instalacao","title":"Passo a Passo de Instala\u00e7\u00e3o","text":""},{"location":"gestao/manual-de-instalacao/#1-clonar-os-repositorios","title":"1. Clonar os Reposit\u00f3rios","text":"

Clone os reposit\u00f3rios do projeto em suas respectivas pastas.

# Clonar o frontend\n$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-FRONT\n\n# Clonar o backend de usu\u00e1rios\n$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-BACKEND-USUARIOS\n\n# Clonar o backend de financeiro\n$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-BACKEND-FINANCEIRO\n\n# Clonar o backend de benef\u00edcios\n$ git clone https://github.com/fga-eps-mds/2024.1-SENTINELA-BACKEND-BENEFICIOS\n\n
"},{"location":"gestao/manual-de-instalacao/#2-configurar-variaveis-de-ambiente","title":"2. Configurar Vari\u00e1veis de Ambiente","text":"

Para cada servi\u00e7o, crie ou edite o arquivo .env na raiz de cada reposit\u00f3rio com as vari\u00e1veis de ambiente necess\u00e1rias. Aqui est\u00e1 um exemplo geral para cada servi\u00e7o:

# Exemplo de .env\nDB_HOST=db  # Endere\u00e7o do banco de dados\nDB_PORT=5432  # Porta do banco de dados\nDB_USER=user  # Usu\u00e1rio do banco de dados\nDB_PASSWORD=senha  # Senha do banco de dados\nDB_NAME=nome_do_banco  # Nome do banco de dados\nPORT=3000  # Porta que o servi\u00e7o vai rodar\n

Certifique-se de que as vari\u00e1veis estejam corretamente configuradas em cada microservi\u00e7o.

"},{"location":"gestao/manual-de-instalacao/#3-subir-os-containers-com-docker","title":"3. Subir os Containers com Docker","text":"

Navegue at\u00e9 a pasta de cada servi\u00e7o e execute os comandos abaixo para rodar os containers com Docker. Abaixo est\u00e1 o passo a passo para cada servi\u00e7o:

"},{"location":"gestao/manual-de-instalacao/#31-frontend","title":"3.1 Frontend","text":"

Entre na pasta do frontend e execute os seguintes comandos:

$ cd frontend\n$ docker build nome-da-imagem\n$ docker run --name nome-do-container -p 5173:5173 nome-da-imagem\n\n

O frontend estar\u00e1 dispon\u00edvel em: http://localhost:5173 (ou a porta especificada no .env).

"},{"location":"gestao/manual-de-instalacao/#32-backend-usuarios","title":"3.2 Backend - Usu\u00e1rios","text":"

Entre na pasta do backend de usu\u00e1rios e execute:

$ cd backend-usuarios\n$ docker-compose up --build\n

Este servi\u00e7o estar\u00e1 dispon\u00edvel na porta configurada no .env, como http://localhost:3001.

"},{"location":"gestao/manual-de-instalacao/#33-backend-financeiro","title":"3.3 Backend - Financeiro","text":"

Entre na pasta do backend financeiro e execute:

$ cd backend-financeiro\n$ docker-compose up --build\n

Este servi\u00e7o estar\u00e1 dispon\u00edvel na porta configurada no .env, como http://localhost:3002.

"},{"location":"gestao/manual-de-instalacao/#34-backend-beneficios","title":"3.4 Backend - Benef\u00edcios","text":"

Entre na pasta do backend de benef\u00edcios e execute:

$ cd backend-beneficios\n$ docker-compose up --build\n

Este servi\u00e7o estar\u00e1 dispon\u00edvel na porta configurada no .env, como http://localhost:3003.

"},{"location":"gestao/manual-de-instalacao/#monitoramento-dos-containers","title":"Monitoramento dos Containers","text":"

Voc\u00ea pode verificar o status de todos os containers em execu\u00e7\u00e3o utilizando o comando:

$ docker ps\n

Caso queira parar todos os servi\u00e7os, navegue at\u00e9 cada reposit\u00f3rio e execute:

$ docker-compose down --volumes\n

Para remover containers que n\u00e3o est\u00e3o mais em execu\u00e7\u00e3o criados pelos docker-compose:

$ docker-compose rm -f\n
"},{"location":"gestao/manual-de-instalacao/#consideracoes-finais","title":"Considera\u00e7\u00f5es Finais","text":"

Com os containers configurados e em execu\u00e7\u00e3o, a aplica\u00e7\u00e3o completa estar\u00e1 dispon\u00edvel para uso. Certifique-se de que todas as portas configuradas estejam livres e que as depend\u00eancias de rede entre os microservi\u00e7os estejam funcionando corretamente (como a comunica\u00e7\u00e3o entre backends e o banco de dados). Para quaisquer problemas, consulte os logs dos containers com o comando:

docker logs <nome_do_container>\n

Caso precise recriar os containers, sempre utilize o par\u00e2metro --build ao rodar o docker-compose para garantir que a imagem seja recompilada.

docker-compose up --build\n
"},{"location":"gestao/manual-de-instalacao/#historico-de-versoes","title":"Hist\u00f3rico de Vers\u00f5es","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Ingrid Carvalho Revis\u00e3o 08/09/24 Sara Campos"},{"location":"gestao/melhorias-defeitos/","title":"Melhorias e defeitos identificados no projeto","text":"

Ao longo do desenvolvimento, foram identificadas evolu\u00e7\u00f5es corretivas e adaptativas, bem como bugs de funcionamento, todos apresentados neste documento.

A qualidade de entrega sempre foi considerada como essencial para o time, de forma que, sempre que algum integrante identificava alguma oportunidade de adapta\u00e7\u00e3o ou corre\u00e7\u00e3o no produto, antes ou depois da aceita\u00e7\u00e3o por parte dos P.Os, o encaminhamento era feito.

Assim, foram adicionadas issues de Enhancement relacionadas \u00e0s US que apresentavam essa necessidade. No total, foram instanciadas tr\u00eas melhorias, das quais duas foram conduzidas e entregues aos P.Os.

ENH US Descri\u00e7\u00e3o Entrega #105 US02 Evolu\u00e7\u00e3o adaptativa da US02 (Solicitar filia\u00e7\u00e3o), que implica na necessidade dos campos Sexo, Lota\u00e7\u00e3o, \u00d3rg\u00e3o e Situa\u00e7\u00e3o Atual se tornarem obrigat\u00f3rios e os campos \u00d3rg\u00e3o e Lota\u00e7\u00e3o devem se tornam campos do tipo Dropdown. Entregue #108 US05 Evolu\u00e7\u00e3o corretiva que apresente feedback para o usu\u00e1rio ao alterar o nome de conta banc\u00e1ria para string vazia Entregue #106 US04 Ajuste do banco de dados, de forma que, a tabela de sindicalizados seja filha da tabela usu\u00e1rios (heran\u00e7a) e reflexo disso no frontend, ou seja, exibi\u00e7\u00e3o dos dados na tela conforme tipo de usu\u00e1rio. N\u00e3o finalizada

Al\u00e9m disso, foi instanciada a necessidade de duas novas US no Backlog do Produto, das quais uma foi trazida para desenvolvimento nesse semestre, devido a sua prioridade (US35 - Cadastrar \u00f3rg\u00e3os/lota\u00e7\u00f5es), e a outra foi identificada para ser desenvolvida futuramente, em outros semestres (US36 - Cadastrar postos de trabalho).

A n\u00e3o finaliza\u00e7\u00e3o da US04, assim como a n\u00e3o entrega da ENH-US04 implicam na necessidade de revis\u00e3o e refatoramento dos formul\u00e1rios referentes a filia\u00e7\u00e3o e cadastro de usu\u00e1rios do tipo filiado, o que deve ser conduzido futuramente pelos pr\u00f3ximos times respons\u00e1veis.

Com rela\u00e7\u00e3o a defeitos, alguns foram identificados ao longo do projeto conforme retorno do usu\u00e1rio nos testes de aceita\u00e7\u00e3o. Todos estes pedidos foram encaminhados para corre\u00e7\u00e3o e entregues de acordo, permitindo assim a entrega final das US.

Nas semanas finais (Release N), quando o foco era na entrega de melhorias e corre\u00e7\u00f5es, o time criou um Mapeamento de Bugs a serem corrigidos, bem como foram inspecionados minuciosamente os estilos (CSS/HTML) de algumas p\u00e1ginas para garantir uma boa Experi\u00eancia de Usu\u00e1rio. Foram elas:

  • contributionHistoric [feito]
  • fornecedores (create and update) [feito]
  • list roles page [feito]
  • list user [feito]
  • profile (update) [feito]

Por fim, o projeto \u00e9 finalizado com a necessidade das seguintes corre\u00e7\u00f5es de defeitos:

US Defeito Descri\u00e7\u00e3o Prioridade US04 Inicialmente, havia sido levantado que as telas de cadastro de usu\u00e1rios teriam os dados pedidos pelos P.Os. No entanto, enquanto era desenvolvida, notou-se que essa US precisava de telas para representar usu\u00e1rios do tipo filiados. Essa corre\u00e7\u00e3o, no entanto, n\u00e3o foi finalizada a n\u00edvel de interface. A corre\u00e7\u00e3o foi feita apenas a n\u00edvel de banco de dados, j\u00e1 que agora as tabelas Usu\u00e1rio e Filiado possuem rela\u00e7\u00e3o de heran\u00e7a, mas \u00e9 preciso criar prot\u00f3tipos de como essas telas ir\u00e3o funcionar com a mudan\u00e7a e refletir isso no frontend. A prioridade dessa corre\u00e7\u00e3o \u00e9 considerada alta, pois afeta a performance de outras US e \u00e9 uma funcionalidade b\u00e1sica do sistema. US34 Quando uma solicita\u00e7\u00e3o \u00e9 rejeitada, um email deve ser enviado ao solicitante para que ele seja informado sobre a rejei\u00e7\u00e3o e, caso queira, entre em contato com o sindicato Esse defeito deve ser corrigido com uma revis\u00e3o simples do c\u00f3digo, visto que, a funcionalidade foi implementada e j\u00e1 havia sido testada antes, mas no momento do teste de aceita\u00e7\u00e3o final do usu\u00e1rio acabou n\u00e3o funcionando perfeitamente A prioridade dessa corre\u00e7\u00e3o n\u00e3o \u00e9 t\u00e3o alta por n\u00e3o afetar outras US, mas por ser uma corre\u00e7\u00e3o r\u00e1pida pode ser significativamente priorizada. US20 Campo de data com formato MM/DD/YYYY Cadastros antigos feitos antes de uma corre\u00e7\u00e3o em rela\u00e7\u00e3o a data ainda exibem formato MM/DD/YY, ao contr\u00e1rio de DD/MM/YYYY, como era esperado, apesar deste problema n\u00e3o ser mais ger\u00e1vel pelos cadastros do usu\u00e1rio Baixa prioridade, n\u00e3o afeta outras US US20 Campo de Conta Origem/Destino n\u00e3o recebe contas banc\u00e1rias cadastradas Quando selecionada a op\u00e7\u00e3o de Conta do Sindicato, as contas banc\u00e1rias que aparecem como op\u00e7\u00e3o de preenchimento s\u00e3o est\u00e1ticas Prioridade alta, por\u00e9m de baixa complexidade, j\u00e1 que basta uma corre\u00e7\u00e3o, implementando a requisi\u00e7\u00e3o GET de Contas Banc\u00e1rias registradas no sistema US21 Desfazer sel\u00e7\u00e3o de filtro \u00c9 poss\u00edvel limpar todos os filtros, no entanto, o P.O fez a sugest\u00e3o de implementar a limpar um filtro por vez Prioridade a ser avaliada pelo P.O"},{"location":"gestao/melhorias-defeitos/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos Atualiza\u00e7\u00e3o a partir do feedback do P.O (Adiciona tabela de Defeitos) 09/09/24 Sara Campos Atualiza\u00e7\u00e3o a partir do feedback do P.O (Adiciona tabela de Defeitos) 14/09/24 Sara Campos"},{"location":"gestao/metodologia/","title":"Metodologia de Trabalho da Equipe","text":""},{"location":"gestao/metodologia/#introducao","title":"Introdu\u00e7\u00e3o","text":"

Para as fases inicias do projeto, foi adotada a metodologia de Lean Inception, que foi abordada em mais detalhes na aba hom\u00f4nima, iniciada no Dia 1.

Nossa equipe adotou uma metodologia de desevolvimento h\u00edbrida baseada em Scrum e pr\u00e1ticas do Extreme Programming (XP), Kanban e PMBOK para garantir um desenvolvimento \u00e1gil e eficiente. Este documento detalha os processos e ferramentas que utilizamos para organizar e comunicar nosso trabalho.

"},{"location":"gestao/metodologia/#framework-scrum","title":"Framework Scrum","text":""},{"location":"gestao/metodologia/#1-sprints","title":"1. Sprints","text":"
  • O Scrum traz uma abordagem que ocorre ao longo sprints, que s\u00e3o esses per\u00edodos de tempo (geralmente uma semana), dentro dos quais s\u00e3o planejadas metas de trabalho a serem realizados.
"},{"location":"gestao/metodologia/#2-planning","title":"2. Planning","text":"
  • Objetivo: Definir as metas e tarefas para o pr\u00f3ximo ciclo de desenvolvimento.
  • Frequ\u00eancia: Toda segunda 21h ap\u00f3s reuni\u00e3o com cliente
  • Participantes: Toda a equipe
  • Atividades:
  • Revisar o backlog de produto
  • Estimar as tarefas utilizando m\u00e9todos como Planning Poker
  • Definir as prioridades e selecionar as tarefas para o sprint
"},{"location":"gestao/metodologia/#3-standup-meeting","title":"3. Standup meeting","text":"
  • Objetivo: Alinhar o progresso e identificar impedimentos.
  • Frequ\u00eancia: Ter\u00e7as e quintas entre aulas
  • Participantes: Toda a equipe
  • Atividades:
  • Novas atividades podem ser repassadas
  • Cada membro responde \u00e0s perguntas:
    • O que estou fazendo?
    • H\u00e1 algum impedimento no meu caminho?
"},{"location":"gestao/metodologia/#4-review","title":"4. Review","text":"
  • Objetivo: Apresentar o trabalho realizado durante a sprint e validar com o PO.
  • Frequ\u00eancia: Toda segunda 20h em reuni\u00e3o com cliente
  • Participantes: Toda a equipe, incluindo stakeholders
  • Atividades:
  • Demonstra\u00e7\u00e3o das funcionalidades desenvolvidas
  • Feedback dos stakeholders
  • Atualiza\u00e7\u00e3o do backlog com base no feedback recebido
"},{"location":"gestao/metodologia/#5-retrospectiva","title":"5. Retrospectiva","text":"
  • Objetivo: Refletir sobre o sprint passado e identificar melhorias para os pr\u00f3ximos sprints.
  • Frequ\u00eancia: Toda sexta-feira \u00e0s 16h
  • Participantes: Toda a equipe
  • Atividades:
  • Discuss\u00e3o sobre o que funcionou bem e o que pode ser melhorado
  • Defini\u00e7\u00e3o de a\u00e7\u00f5es para melhorias cont\u00ednuas
"},{"location":"gestao/metodologia/#6-papeis","title":"6. Pap\u00e9is","text":"
  • O Scrum sugere os pap\u00e9is de Product Owner e Scrum Master. Neste trabalho, os representantes do SINDPOL-DF (Matheus Amaral e Davi Mendon\u00e7a) tiveram uma atua\u00e7\u00e3o semelhante a proposta de um Product Owner, representando as necessidades do cliente. Enquanto isso, os estudantes de EPS puderam assumir o papel de Scrum Master, gerenciando, treinando e orientando a Equipe de Desenvolvimento (estudantes de MDS e, em dados momentos, EPS) para cumprir as regras de Scrum e entregar os resultados.
"},{"location":"gestao/metodologia/#praticas-do-extreme-programming-xp","title":"Pr\u00e1ticas do Extreme Programming (XP)","text":""},{"location":"gestao/metodologia/#1-programacao-em-pares","title":"1. Programa\u00e7\u00e3o em Pares","text":"
  • Objetivo: Melhorar a qualidade do c\u00f3digo e promover o compartilhamento de conhecimento.
  • Como funciona: Dois desenvolvedores trabalham juntos no mesmo c\u00f3digo, alternando entre os pap\u00e9is de \u201cDriver\u201d e \u201cObserver\u201d. Neste trabalho, houveram momentos em que a programa\u00e7\u00e3o envolvia inclusive mais de duas pessoas, em momentos cr\u00edticos e quando c\u00f3digos eram debugados. Al\u00e9m disso, o time realizou duas reuni\u00f5es extraordin\u00e1rias com a presen\u00e7a de todos integrantes para codar num ambiente em que o grupo como um todo poderia se apoiar e parear conforme necessidade.
"},{"location":"gestao/metodologia/#2-integracao-continua-cicd","title":"2. Integra\u00e7\u00e3o Cont\u00ednua (CI/CD)","text":"
  • Objetivo: Assegurar que o c\u00f3digo est\u00e1 sempre em um estado funcional.
  • Como funciona: O c\u00f3digo \u00e9 integrado e testado automaticamente no SonarQube, permitindo coletar m\u00e9tricas do c\u00f3digo rapidamente.
"},{"location":"gestao/metodologia/#3-proximidade-com-o-usuario","title":"3. Proximidade com o Usu\u00e1rio","text":"
  • Objetivo: Garantir que o desenvolvimento est\u00e1 alinhado com as necessidades e expectativas do usu\u00e1rio.
  • Como funciona: Envolvimento constante do usu\u00e1rio final durante o processo de desenvolvimento, com feedback frequente e ajustes conforme necess\u00e1rio.
"},{"location":"gestao/metodologia/#4-cadencia-rapida-de-entregas","title":"4. Cad\u00eancia R\u00e1pida de Entregas","text":"
  • Objetivo: Entregar incrementos de valor ao cliente de forma cont\u00ednua e r\u00e1pida.
  • Como funciona: Entregas frequentes e menores, focando na entrega cont\u00ednua de valor ao cliente por meio de releases (vers\u00f5es do produto). Com a defini\u00e7\u00e3o de tr\u00eas releases major no per\u00edodo da disciplina, foram planejadas as entregas de cada uma, de forma que, o trabalho dentro das sprints do Scrum era executado a fim de atingir essas metas.
"},{"location":"gestao/metodologia/#5-testes","title":"5. Testes","text":"
  • Objetivo: Essa pr\u00e1tica viabiliza a integra\u00e7\u00e3o cont\u00ednua e busca monitorar a qualidade do produto, garantindo que seu comportamento seja condizente com o esperado.
  • Como funciona: No c\u00f3digo fonte s\u00e3o realizados testes unit\u00e1ios desenvolvidos pela Equipe de Desenvolvimento, enquanto no ambiente de produ\u00e7\u00e3o s\u00e3o feitos testes de aceita\u00e7\u00e3o/testes manuais realizados pelos P.Os e pela Equipe de Desenvolvimento.
"},{"location":"gestao/metodologia/#kanban","title":"Kanban","text":""},{"location":"gestao/metodologia/#uso-do-quadro-kanban","title":"Uso do Quadro Kanban","text":"
  • Objetivo: Visualizar o fluxo de trabalho e limitar o trabalho em progresso.
  • Como funciona: As tarefas s\u00e3o movidas atrav\u00e9s de colunas no quadro, representando diferentes est\u00e1gios do fluxo de trabalho (Ex.: Backlog, Em Progresso, Em Revis\u00e3o, Conclu\u00eddo). Foi usado o Zenhub criar essa visualiza\u00e7\u00e3o de progresso das atividades e, ao passo que foi notado gargalo de trabalho em andamento, os Scrum Masters tomaram decis\u00e3o de n\u00e3o iniciar novas hist\u00f3rias e focar em finalizar entregas de qualidade do que estava In Progress.
"},{"location":"gestao/metodologia/#pmbok","title":"PMBOK","text":""},{"location":"gestao/metodologia/#gestao-de-projetos","title":"Gest\u00e3o de Projetos","text":"
  • Objetivo: Integrar pr\u00e1ticas de gerenciamento de projetos para melhor organiza\u00e7\u00e3o e controle.
  • Como funciona: Utiliza-se as \u00e1reas de conhecimento do PMBOK, como gerenciamento de escopo, tempo, custo e qualidade, adaptando-as ao contexto \u00e1gil da equipe. O escopo foi gerenciado pelos Srum Masters com acompanhamento dos P.Os ao longo do semestre, considerando o que havia sido planejado inicialmente e a viabilidade conforme o andamento do trabalho. O custo tamb\u00e9m foi monitorado por meio de documentos como Custo, com acompanhamento semanal/total do custo, e EVM, com os resultados de Valor Agregado e Valor Planejado. O documento de Riscos demonstra o relato semanal/por sprint dos riscos identificados e seus respectivos graus de probabilidade e impacto, bem como os planejamentos de respostas a cada um deles.
"},{"location":"gestao/metodologia/#grupos-de-processos","title":"Grupos de processos","text":"
  • Objetivo: Definir o ciclo de vida do projeto.
  • Como funciona: Apesar de discordar um pouco da vis\u00e3o \u00e1gil nesse sentido, o PMBOK traz um conjunto de fases pelas quais o projeto passa dentro do seu cronograma de execu\u00e7\u00e3o. Essa vis\u00e3o foi trazida na EAP, onde tem-se os grupos de processos Inicia\u00e7\u00e3o, Planejamento, Execu\u00e7\u00e3o e Encerramento. Essa vis\u00e3o \u00e9 uma abstra\u00e7\u00e3o do m\u00e9todo, visto que, as atividades nem sempre s\u00e3o resumidas apenas a um grupo de processos, como \u00e9 a proposta do \u00e1gil.
"},{"location":"gestao/metodologia/#conclusao","title":"Conclus\u00e3o","text":"

Adotando essa combina\u00e7\u00e3o de Scrum, XP, Kanban e PMBOK, visamos a maximiza\u00e7\u00e3o da produtividade e a qualidade do nosso produto final. As ferramentas escolhidas suportam nossas necessidades de comunica\u00e7\u00e3o e organiza\u00e7\u00e3o, facilitando a colabora\u00e7\u00e3o e a transpar\u00eancia em todas as fases do desenvolvimento.

"},{"location":"gestao/metodologia/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento Victor Yukio Revis\u00e3o 18/07/24 Sara Campos Revis\u00e3o 03/08/24 Sara Campos Revis\u00e3o conforme apontamentos da Release Final 14/09/24 Sara Campos"},{"location":"gestao/metodologia/#referencias","title":"Refer\u00eancias","text":"

Scrum: Como fazer mais em menos tempo. Acessado em 14/09/2024. Pr\u00e1ticas em XP: Extreme Programming. Acessado em 14/09/2024.

"},{"location":"gestao/planoQualidade/","title":"Plano de Qualidade","text":""},{"location":"gestao/planoQualidade/#introducao","title":"Introdu\u00e7\u00e3o","text":"

De acordo com a ISO 25010, a qualidade de um produto de software \u00e9 definida pelo grau em que ele atende aos requisitos de seus usu\u00e1rios, agregando valor. Esses requisitos, que incluem funcionalidade, desempenho, seguran\u00e7a, manutenibilidade, entre outros, s\u00e3o representados no modelo de qualidade, que categoriza a qualidade do produto em caracter\u00edsticas e subcaracter\u00edsticas. Para alcan\u00e7ar esses requisitos, \u00e9 essencial desenvolver e monitorar m\u00e9tricas de forma cont\u00ednua. O objetivo do planejamento de qualidade \u00e9 descrever como esse monitoramento foi realizado durante o projeto.

"},{"location":"gestao/planoQualidade/#processo-de-qualidade","title":"Processo de Qualidade","text":"

Para garantir a qualidade do projeto, integramos cada servi\u00e7o desenvolvido com a ferramenta SonarQube, utilizando a interface SonarCloud para proporcionar uma an\u00e1lise mais amig\u00e1vel e detalhada de todas as m\u00e9tricas coletadas. O processo \u00e9 orientado pela valida\u00e7\u00e3o das US com o cliente, utilizando prot\u00f3tipos e crit\u00e9rios de aceita\u00e7\u00e3o, seguido pela implementa\u00e7\u00e3o cont\u00ednua de melhorias. Ap\u00f3s o desenvolvimento, as funcionalidades passam pelos testes de aceita\u00e7\u00e3o conduzidos pelo cliente, assegurando que ajustes e aperfei\u00e7oamentos sejam aplicados. Caso novas melhorias sejam identificadas, elas s\u00e3o incorporadas ao processo de desenvolvimento, refor\u00e7ando a qualidade do produto.

"},{"location":"gestao/planoQualidade/#metricas-monitoradas","title":"M\u00e9tricas Monitoradas:","text":"
  • Cobertura de C\u00f3digo
  • Duplica\u00e7\u00e3o de C\u00f3digo
  • Vulnerabilidades e Bugs
  • Integra\u00e7\u00e3o com CI/CD: Configura\u00e7\u00e3o do SonarCloud com pipelines de integra\u00e7\u00e3o cont\u00ednua.
  • Alertas e Relat\u00f3rios: Configura\u00e7\u00e3o de thresholds para alertas autom\u00e1ticos e gera\u00e7\u00e3o de relat\u00f3rios.
"},{"location":"gestao/planoQualidade/#politicas-de-codigo-e-revisao","title":"Pol\u00edticas de C\u00f3digo e Revis\u00e3o","text":"
  • Pull Requests e Code Review: Processo de revis\u00e3o de c\u00f3digo e melhores pr\u00e1ticas para garantir qualidade.
  • Padr\u00f5es de Codifica\u00e7\u00e3o: Ferramentas e regras aplicadas para padroniza\u00e7\u00e3o do c\u00f3digo.
  • Merge Guidelines: Crit\u00e9rios para fus\u00e3o de branches e deploy.
"},{"location":"gestao/planoQualidade/#ferramentas-de-teste","title":"Ferramentas de Teste","text":"

Jest: Framework de testes completo para JavaScript, amplamente usado para testes de unidade, integra\u00e7\u00e3o e ponta a ponta. Oferece suporte a mocks, snapshots, e uma interface f\u00e1cil de usar.

Vitest: Framework de testes r\u00e1pido e leve, projetado para o ecossistema JavaScript, com foco em integra\u00e7\u00e3o com Vite. Suporta mocks, TypeScript e testes ESM, acelerando o desenvolvimento front-end.

SonarCloud: plataforma de an\u00e1lise de c\u00f3digo que identifica bugs, vulnerabilidades e code smells. Oferece suporte a v\u00e1rias linguagens, integrando-se facilmente ao fluxo CI/CD para garantir a qualidade do c\u00f3digo.

ZenHub: ferramenta de gerenciamento de projetos que se integra ao GitHub, oferecendo recursos como quadros kanban e relat\u00f3rios de produtividade

"},{"location":"gestao/planoQualidade/#acompanhamento-de-metricas-do-sonar","title":"Acompanhamento de m\u00e9tricas do sonar","text":""},{"location":"gestao/planoQualidade/#release-1","title":"Release 1","text":"

Funcionalidades presentes:

  • US01 - Fazer login
  • US02 - Solicitar filia\u00e7\u00e3o
  • US04 - Cadastrar usu\u00e1rios
  • US33 - Atualizar dados de usu\u00e1rio
"},{"location":"gestao/planoQualidade/#release-2","title":"Release 2","text":"

Funcionalidades presentes:

  • US02 - Solicitar filia\u00e7\u00e3o (Ajustes pedidos na Release 1)
  • US19- Cadastrar benef\u00edcios
  • US34 - Gerenciar filia\u00e7\u00f5es
"},{"location":"gestao/planoQualidade/#release-3","title":"Release 3","text":"

Funcionalidades presentes:

  • US03 - Cadastrar fornecedores
  • US05 - Cadastrar contas banc\u00e1rias
  • US17 - Cadastrar perfis no sistema
"},{"location":"gestao/planoQualidade/#release-mvp","title":"Release MVP","text":"

Funcionalidades presentes:

  • US01 - Fazer login no sistema (Ajustes pedidos na Release 1)
  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release 3)
  • US16 - Visualizar dashboard sobre os sindicalizados
  • US20 - Cadastrar movimenta\u00e7\u00f5es financeiras
  • US23 - Consulta do Hist\u00f3rico de Contribui\u00e7\u00f5es do sindicalizado
  • US35 - Cadastro de \u00f3rg\u00e3o/lota\u00e7\u00e3o
  • US34 - Gerenciar solicita\u00e7\u00f5es de filia\u00e7\u00e3o (Ajustes pedidos na Release 2)
"},{"location":"gestao/planoQualidade/#release-5","title":"Release 5","text":"

Funcionalidades presentes:

  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release MVP)
  • US20 - Cadastrar movimenta\u00e7\u00f5es financeiras (Ajustes pedidos na Release MVP)
  • US17 - Cadastrar perfis (Ajustes necess\u00e1rios identificados na Release MVP)
  • US18 - Atribuir perfis
  • US21 - Gerar relat\u00f3rio de movimenta\u00e7\u00f5es financeiras
  • ENH-US02 - Melhorias da US02
  • ENH-US05 - Melhorias da US05
"},{"location":"gestao/planoQualidade/#modelo-de-qualidade-do-q-rapids","title":"Modelo de Qualidade do Q-Rapids","text":"

Foi seguido o modelo de qualidade Q-Rapids. Ele foi projetado para auxiliar equipes de desenvolvimento a tomar decis\u00f5es informadas com base em m\u00e9tricas de qualidade e dados em tempo real, coletados automaticamente ao longo do ciclo de vida do software. O SonarCloud, plataforma de apoio para monitoramento de m\u00e9tricas de integra\u00e7\u00e3o cont\u00ednua, integra diferentes fontes de informa\u00e7\u00e3o para gerar relat\u00f3rios e dashboards que oferecem uma vis\u00e3o detalhada sobre a sa\u00fade do projeto. Seu objetivo principal \u00e9 melhorar a qualidade do software, facilitar a gest\u00e3o de riscos e otimizar processos, permitindo que as equipes sejam mais \u00e1geis e eficazes na entrega de software.

Os fatores e m\u00e9tricas de qualidade s\u00e3o crit\u00e9rios usados para avaliar a efici\u00eancia, desempenho e confiabilidade de um produto de software, seu processo de desenvolvimento e a organiza\u00e7\u00e3o como um todo. Esses fatores, como manutenibilidade, confiabilidade, usabilidade e efici\u00eancia, ajudam a medir qu\u00e3o bem o software atende aos requisitos t\u00e9cnicos e \u00e0s expectativas dos usu\u00e1rios. As m\u00e9tricas associadas fornecem dados quantitativos que permitem monitorar e melhorar a qualidade continuamente. Utiliz\u00e1-las \u00e9 essencial para identificar problemas precocemente, aumentar a satisfa\u00e7\u00e3o do cliente, reduzir custos com retrabalho e garantir o alinhamento do produto com os objetivos estrat\u00e9gicos da organiza\u00e7\u00e3o.

"},{"location":"gestao/planoQualidade/#metricas","title":"M\u00e9tricas","text":"

As m\u00e9tricas definidas para o Sentinela foram:

M\u00e9trica Descri\u00e7\u00e3o Files Quantidade de arquivos de c\u00f3digo Functions Quantidade de fun\u00e7\u00f5es no c\u00f3digo Complexity Complexidade cognitiva Comment Lines Density Densidade (%) de linhas comentadas Duplicated Lines density Densidade (%) de linhas duplicadas Coverage Cobertura de c\u00f3digo pelos testes Ncloc Quantidade de linhas de c\u00f3digo Tests Testes unit\u00e1rios e de integra\u00e7\u00e3o Test Errors Testes que possuem erros Test Failures Testes que falharam Test Execution Time Tempo de execu\u00e7\u00e3o dos testes Security Rating Avalia\u00e7\u00e3o de seguran\u00e7a de falhas e vulnerabilidades"},{"location":"gestao/planoQualidade/#metricas-para-o-produto","title":"M\u00e9tricas para o produto","text":"

O uso de m\u00e9tricas permite identificar subcaracter\u00edsticas associadas e avaliar a qualidade do produto. Essa an\u00e1lise tamb\u00e9m possibilita medir a produtividade do projeto, gerando resultados que influenciam as decis\u00f5es de desenvolvimento. Com base nas m\u00e9tricas especificadas no SonarCloud e Q-Rapids, al\u00e9m dos dados coletados, foram definidos os valores m\u00ednimos aceit\u00e1veis para cada m\u00e9trica no projeto Sentinela, conforme mostrado nas tabelas abaixo. Os dados refer\u00eantes a satisfa\u00e7\u00e3o do usu\u00e1rio foram coletados a partir do formul\u00e1rio fornecido aos POs, que visa quantificar em escala de 1 a 5 qual o n\u00edvel de satisfa\u00e7\u00e3o do cliente quanto ao trabalho realizado e entregue pelo grupo Sentinela 2024/1, baseado nos modelos CSAT e NPS.

"},{"location":"gestao/planoQualidade/#repositorio-do-frontend","title":"Reposit\u00f3rio do Frontend","text":"M\u00e9trica Valor refer\u00eancia Valor alcan\u00e7ado Complexity at\u00e9 10 9 Comment Lines Density (%) at\u00e9 30% 1,9% Duplicated Lines Density (%) at\u00e9 5% 7% Coverage acima de 80% 78,1% Test Failures 0 0 Test Errors 0 0 Security Rating 0 (A) 0 (A) Satisfa\u00e7\u00e3o do usu\u00e1rio acima de 3 5"},{"location":"gestao/planoQualidade/#repositorio-do-backend-usuarios","title":"Reposit\u00f3rio do Backend - Usu\u00e1rios","text":"M\u00e9trica Valor refer\u00eancia Valor alcan\u00e7ado Complexity at\u00e9 10 3 Comment Lines Density (%) at\u00e9 30% 4,7% Duplicated Lines Density (%) at\u00e9 5% 0,0% Coverage acima de 80% 78,2 Test Failures 0 0 Test Errors 0 0 Security Rating 0 (A) 0 (A) Satisfa\u00e7\u00e3o do usu\u00e1rio acima de 3 5"},{"location":"gestao/planoQualidade/#repositorio-do-backend-financeiro","title":"Reposit\u00f3rio do Backend - Financeiro","text":"M\u00e9trica Valor refer\u00eancia Valor alcan\u00e7ado Complexity at\u00e9 10 1 Comment Lines Density (%) at\u00e9 30% 5,5% Duplicated Lines Density (%) at\u00e9 5% 0,0% Coverage acima de 80% 86,5% Test Failures 0 0 Test Errors 0 0 Security Rating 0 (A) 0 (A) Satisfa\u00e7\u00e3o do usu\u00e1rio acima de 3 5"},{"location":"gestao/planoQualidade/#repositorio-do-backend-beneficios","title":"Reposit\u00f3rio do Backend - Benef\u00edcios","text":"M\u00e9trica Valor refer\u00eancia Valor alcan\u00e7ado Complexity at\u00e9 10 2 Comment Lines Density (%) at\u00e9 30% 4,7% Duplicated Lines Density (%) at\u00e9 5% 0,0% Coverage acima de 80% 78% Test Failures 0 0 Test Errors 0 0 Security Rating 0 (A) 1 (E) Satisfa\u00e7\u00e3o do usu\u00e1rio acima de 3 5"},{"location":"gestao/planoQualidade/#historico-de-versoes","title":"Hist\u00f3rico de Vers\u00f5es","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 28/07/24 Ingrid Carvalho Atualiza\u00e7\u00f5es sobre o sonar 31/08/2024 Ingrid Carvalho Atualiza\u00e7\u00f5es com as m\u00e9tricas 08/09/2024 Ingrid Carvalho Revis\u00e3o 08/09/2024 Sara Campos"},{"location":"gestao/planoQualidade/#referencias","title":"Refer\u00eancias","text":"

ISO/IEC 25010

"},{"location":"gestao/riscos/","title":"Riscos do Projeto Sentinela","text":""},{"location":"gestao/riscos/#introducao","title":"Introdu\u00e7\u00e3o","text":"

O projeto Sentinela envolve o desenvolvimento colaborativo de um software e, para garantir seu sucesso, \u00e9 essencial identificar, avaliar e mitigar os riscos que possam impactar o projeto. A seguir, s\u00e3o descritos os principais riscos mapeados, suas probabilidades e impactos, al\u00e9m das estrat\u00e9gias de monitoramento cont\u00ednuo. Abaixo pode-se visualizar o Mapeamento de Riscos e Gr\u00e1fico de Riscos

"},{"location":"gestao/riscos/#lista-de-riscos-do-projeto-sentinela","title":"Lista de Riscos do Projeto Sentinela","text":"

As categorias de riscos no projeto Sentinela s\u00e3o divididas em cinco grupos principais: Organizacional, T\u00e9cnico, Qualidade, Ger\u00eancia e Externo. Os riscos organizacionais envolvem desafios relacionados ao comprometimento da equipe, comunica\u00e7\u00e3o e motiva\u00e7\u00e3o, podendo gerar atrasos e conflitos internos. Os t\u00e9cnicos abordam dificuldades com tecnologias, arquitetura, deploy e ambienta\u00e7\u00e3o, que podem impactar diretamente o desenvolvimento e entrega da aplica\u00e7\u00e3o. J\u00e1 os riscos de qualidade tratam de problemas como aus\u00eancia de testes, falhas de UX/UI e m\u00e1 pr\u00e1tica no processo de desenvolvimento, afetando a experi\u00eancia do usu\u00e1rio e a adequa\u00e7\u00e3o do produto aos requisitos. Na categoria de ger\u00eancia, est\u00e3o os riscos relacionados \u00e0 defini\u00e7\u00e3o de escopo, gest\u00e3o de tempo, cronograma e pontua\u00e7\u00e3o de US, que podem comprometer o andamento eficiente do projeto. Por fim, os riscos externos s\u00e3o imprevistos fora do controle da equipe, como suspens\u00e3o de aulas, infraestrutura inadequada e afastamento de integrantes, que podem gerar interrup\u00e7\u00f5es no progresso do projeto.

"},{"location":"gestao/riscos/#1-organizacional","title":"1. Organizacional","text":"
  1. Falha de comunica\u00e7\u00e3o
  2. Descomprometimento da equipe
  3. Erro de prioriza\u00e7\u00e3o
  4. Desist\u00eancia de membros
  5. Desaven\u00e7as entre os membros
  6. Tens\u00e3o de fim de semestre
  7. Falta de motiva\u00e7\u00e3o
  8. Atraso nas entregas
"},{"location":"gestao/riscos/#2-tecnico","title":"2. T\u00e9cnico","text":"
  1. Dificuldade em criar backlog
  2. M\u00e1 escolha das tecnologias
  3. Dificuldade de ambienta\u00e7\u00e3o
  4. Arquitetura mal definida
  5. Dificuldade de deploy da aplica\u00e7\u00e3o
  6. Dificuldade em hospedar a aplica\u00e7\u00e3o
  7. Documenta\u00e7\u00e3o que induz ao erro
  8. Dificuldade com as tecnologias
"},{"location":"gestao/riscos/#3-qualidade","title":"3. Qualidade","text":"
  1. Aus\u00eancia de testes
  2. Falhas e bugs
  3. M\u00e1 implementa\u00e7\u00e3o de UX
  4. M\u00e1 implementa\u00e7\u00e3o de UI
  5. M\u00e1 pr\u00e1tica do processo de desenvolvimento
  6. Aplica\u00e7\u00e3o n\u00e3o atender expectativas do usu\u00e1rio
  7. N\u00e3o cumprimento dos requisitos elicitados
  8. Falta de valida\u00e7\u00e3o com o stakeholder
"},{"location":"gestao/riscos/#4-gerencia","title":"4. Ger\u00eancia","text":"
  1. Escopo mal definido
  2. Mudan\u00e7a arquitetural
  3. M\u00e1 gest\u00e3o do tempo
  4. Cronograma invi\u00e1vel
  5. M\u00e1 pontua\u00e7\u00e3o das US
  6. Problema no gerenciamento da equipe
  7. Sobrecarga de tarefas
  8. Mudan\u00e7as de tecnologias
  9. Hor\u00e1rios divergentes dos integrantes
"},{"location":"gestao/riscos/#5-externo","title":"5. Externo","text":"
  1. Suspens\u00e3o das aulas
  2. Baixa ades\u00e3o da aplica\u00e7\u00e3o
  3. Imprevistos com infraestrutura (internet, energia, computador)
  4. Afastamento de integrante (enfermidade, luto, assist\u00eancia familiar)
  5. Atualiza\u00e7\u00f5es dr\u00e1sticas das tecnologias escolhidas
"},{"location":"gestao/riscos/#monitoramento-continuo-dos-riscos","title":"Monitoramento Cont\u00ednuo dos Riscos","text":"

Gerenciar os riscos \u00e9 um processo cont\u00ednuo e din\u00e2mico. Ao longo do desenvolvimento do projeto Sentinela, novos riscos podem surgir e os riscos existentes podem aumentar ou diminuir em impacto e probabilidade. \u00c9 essencial que a equipe:

  • Realize revis\u00f5es regulares dos riscos identificados.
  • Esteja atenta a novos riscos que possam aparecer.
  • Ajuste as estrat\u00e9gias de mitiga\u00e7\u00e3o conforme necess\u00e1rio.
  • Documente qualquer mudan\u00e7a no impacto e probabilidade dos riscos.

Esse monitoramento constante permite que a equipe reaja proativamente \u00e0s mudan\u00e7as e mantenha o controle sobre os fatores que podem afetar o sucesso do projeto.

"},{"location":"gestao/riscos/#historico-de-versao","title":"Hist\u00f3rico de Vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 22/07/24 Victor Yukio Atualiza\u00e7\u00e3o dos riscos 08/09/24 Ingrid Carvalho Revis\u00e3o 08/09/24 Sara Campos"},{"location":"gestao/roadmap/","title":"Entregas e roadmap","text":"

O Roadmap do projeto foi criado a partir do que foi definido e validado na EAP e atualizado semanalmente conforme o andamento das atividades. Assim, os pacotes de trabalho foram representados no Roadmap, e \u00e9picos (funcionalidades do produto) foram associadas a eles. Os \u00e9picos, por fim, foram associados \u00e0s Hist\u00f3rias de Usu\u00e1rio \u00e0s quais se referiam.

Na data final de entrega do projeto, a situa\u00e7\u00e3o do Roadmap era a seguinte:

O comportamento do roadmap, apesar de aparentar muitos atrasos, era o esperado para o fluxo de trabalho da disciplina, onde normalmente existe um per\u00edodo de espera da aceita\u00e7\u00e3o por parte dos P.Os e retorno de corre\u00e7\u00f5es e melhorias. No geral, observa-se um bom prospecto, i.e das 16 US instanciadas para o projeto neste semestre (15 planejadas e 1 adicionada), foi poss\u00edvel entregar 14 delas.

As US foram divididas em 5 Releases totais (3 Major e 2 minors):

Release 1 (Major):

  • US01 - Fazer login
  • US02 - Solicitar filia\u00e7\u00e3o
  • US04 - Cadastrar usu\u00e1rios
  • US33 - Atualizar dados de usu\u00e1rio

Release 2 (Minor):

  • US17 - Cadastrar perfis no sistema
  • US05 - Cadastrar contas banc\u00e1rias

Release 3 (Minor):

  • US19 - Cadastrar benef\u00edcios
  • US02 - Solicitar filia\u00e7\u00e3o (Ajustes pedidos na Release 1)
  • US34 - Gerenciar filia\u00e7\u00f5es

Release 4/MVP (Major):

  • US01 - Fazer login no sistema (Ajustes pedidos na Release 1)
  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release 3)
  • US16 - Visualizar dashboard sobre os sindicalizados
  • US20 - Cadastrar movimenta\u00e7\u00f5es financeiras
  • US23 - Consulta do Hist\u00f3rico de Contribui\u00e7\u00f5es do sindicalizado
  • US35 - Cadastro de \u00f3rg\u00e3o/lota\u00e7\u00e3o
  • US34 - Gerenciar solicita\u00e7\u00f5es de filia\u00e7\u00e3o (Ajustes pedidos na Release 2)

Release 5/N (Major):

  • US03 - Cadastrar fornecedores (Ajustes pedidos na Release 4)
  • US20 - Cadastrar movimenta\u00e7\u00f5es financeiras (Ajustes pedidos na Release 4)
  • US17 - Cadastrar perfis (Ajustes necess\u00e1rios identificados na Release 4)
  • US18 - Atribuir perfis
  • US21 - Gerar relat\u00f3rio de movimenta\u00e7\u00f5es financeiras
  • ENH-US02 - Melhorias da US02
  • ENH-US05 - Melhorias da US05
"},{"location":"gestao/roadmap/#historico-de-versoes","title":"Hist\u00f3rico de Vers\u00f5es","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"lean/dia1/","title":"Lean Inception - Dia 1","text":""},{"location":"lean/dia1/#visao-do-produto","title":"Vis\u00e3o do Produto","text":"

Nesta etapa, a proposta \u00e9 definir de maneira colaborativa uma ideia inicial do que espera-se do produto atrav\u00e9s de uma frase clara que segue o formato:

Para: [cliente final], Cujo: [problema que precisa ser resolvido], O: [nome do produto] \u00c9 um: [categoria do produto] Que: [benef\u00edcio-chave, raz\u00e3o para adquiri-lo], Diferentemente do: [alternativa da concorr\u00eancia] O nosso produto: [diferen\u00e7a-chave].

"},{"location":"lean/dia1/#reuniao","title":"Reuni\u00e3o","text":"

Data: 01/04/24

Participantes:

Equipe Nomes PO Matheus Amaral, Davi Mendon\u00e7a EPS Ingrid Carvalho, Sara Campos, Victor Yukio, Alvaro Gouvea MDS Anna Brand\u00e3o, Guilherme Storch, Milena Rocha, Jos\u00e9 Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, Jo\u00e3o Victor Nobre

Descri\u00e7\u00e3o:

Em reuni\u00e3o, a din\u00e2mica de Vis\u00e3o do Produto foi apresentada para o cliente e guiada pela estudante Ingrid Carvalho, ao passo que a estudante Sara Campos fazia as anota\u00e7\u00f5es no quadro Figma como pode ser observado aqui.

O objetivo neste momento foi, a partir do quadro criado no semestre 2023/2, validar o que havia sido levantado, al\u00e9m de corrigir poss\u00edveis erros, tentar deixar a frase mais clara e adicionar o que fosse necess\u00e1rio.

Por ser o primeiro contato dos estudantes com o produto, para tentar deixar essa etapa um pouco mais flu\u00edda, foi realizada no dia 28/03/24 uma reuni\u00e3o de \"Pr\u00e9 Lean Inception\" com o PO Matheus Amaral, que explicou brevemente a proposta do sistema e algumas coisas que dever\u00edamos nos atentar neste momento. Assim, foi poss\u00edvel guiar melhor o PO e representante do SINDPOL Davi Mendon\u00e7a na atividade e compreender bem o que foi passado.

Como resultado dessa reuni\u00e3o, conseguimos o seguinte quadro de Vis\u00e3o do Produto:

Ainda nesta reuni\u00e3o, foi iniciada a din\u00e2mica de \u00c9/N\u00e3o\u00e9 - Faz/N\u00e3oFaz. Entretanto, o resultado do quadro s\u00f3 foi finalizado no 2\u00ba dia de Lean Inception.

"},{"location":"lean/dia1/#referencias","title":"Refer\u00eancias","text":"

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

"},{"location":"lean/dia1/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/04/24 Sara Campos"},{"location":"lean/dia2/","title":"Lean Inception - Dia 2","text":""},{"location":"lean/dia2/#enaoe-faznaofaz-enfn","title":"\u00c9/N\u00e3o\u00e9 - Faz/N\u00e3oFaz (ENFN)","text":"

Nesta atividade, busca-se classificar o produto seguindo quatro diretrizes. O ENFN ajuda a esclarecer o produto atrav\u00e9s de uma din\u00e2mica simples onde define-se: o que o produto \u00e9; o que o produto n\u00e3o \u00e9; o que o produto faz; e o que o produto n\u00e3o faz.

"},{"location":"lean/dia2/#reuniao","title":"Reuni\u00e3o","text":"

Data: 02/04/24

Participantes:

Equipe Nomes PO Matheus Amaral, Davi Mendon\u00e7a EPS Ingrid Carvalho, Sara Campos MDS Jos\u00e9 Eduardo, Diogo Barboza, Davi Nobre

Descri\u00e7\u00e3o:

Nesta reuni\u00e3o, a din\u00e2mica de ENFN foi novamente apresentada para o cliente e guiada pela estudante Ingrid Carvalho, ao passo que a estudante Sara Campos fazia as anota\u00e7\u00f5es no quadro Figma como pode ser observado aqui.

\u00c9 importante ressaltar que nessa data, o quadro ENFN foi retomado ap\u00f3s um teste de usabilidade realizado com o prot\u00f3tipo 2023/2. As estudantes EPS presentes chegaram a conclus\u00e3o de que a combina\u00e7\u00e3o do teste, onde navegou-se por uma vers\u00e3o do sistema juntamente com o PO Davi Mendon\u00e7a, seguido pela ENFN ajudou bastante no esclarecimento do produto para os estudantes, assim como refrescou bastante a mem\u00f3ria dos POs presentes que conseguiram trazer com facilidade v\u00e1rias caracter\u00edsticas do produto para o quadro ENFN (especialmente na se\u00e7\u00e3o \"Faz\").

Como resultado dessa reuni\u00e3o, chegou-se ao seguinte quadro ENFN:

"},{"location":"lean/dia2/#referencias","title":"Refer\u00eancias","text":"

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

"},{"location":"lean/dia2/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/04/24 Sara Campos"},{"location":"lean/dia3/","title":"Lean Inception - Dia 3","text":""},{"location":"lean/dia3/#objetivos-do-produto","title":"Objetivos do Produto","text":"

Nesse momento, a proposta \u00e9 resumir o produto em seus objetivos. Assim, as fun\u00e7\u00f5es esperadas que o produto execute s\u00e3o trazidas e clusterizadas.

"},{"location":"lean/dia3/#personas","title":"Personas","text":"

As personas s\u00e3o representa\u00e7\u00f5es dos usu\u00e1rios finais do produto e trazem de forma mais realista quais necessidades aquele produto se prop\u00f5e a atender. Assim, o time consegue levantar as funcionalidades tendo em mente a pessoa que ir\u00e1 usar o sistema.

"},{"location":"lean/dia3/#reuniao","title":"Reuni\u00e3o","text":"

Data: 08/04/24

Participantes:

Equipe Nomes PO Matheus Amaral, Davi Mendon\u00e7a EPS Ingrid Carvalho, Sara Campos, Alvaro Gouvea MDS Anna Brand\u00e3o, Guilherme Storch, Milena Rocha, Jos\u00e9 Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, Jo\u00e3o Victor Nobre

Descri\u00e7\u00e3o:

Em reuni\u00e3o, a din\u00e2mica de Vis\u00e3o do Produto foi apresentada para o cliente e guiada pela estudante Sara Campos, ao passo que a estudante Ingrid Carvalho fazia as anota\u00e7\u00f5es no quadro Figma como pode ser observado aqui.

Neste encontro, iniciamos com os Objetivos do Produto que haviam sido levantados no semestre 2023/2, refinando os textos dos post-its, excluindo duplicatas, especificando os perfis de usu\u00e1rio em cada post-it, aglutinando clusters e adicionando um novo cluster que foi trazido pelos POs. Al\u00e9m disso, com os clusters validados, foi pedido ao PO Davi Mendon\u00e7a que classificasse cada um por prioridade/urg\u00eancia indo de 1 a 7. Dessa forma, chegou-se nesta reuni\u00e3o ao seguinte resultado:

Os Objetivos do Produto ainda devem ser revisados em compara\u00e7\u00e3o com o ENFN, a fim de garantir que nenhum objetivo/fun\u00e7\u00e3o levantado anteriormente tenha sido esquecido na fase anterior.

Em seguida, duas personas constru\u00eddas no semestre 2023/2 foram refinadas e duas novas personas foram criadas. Como pode-se observar abaixo, foram validadas 1 persona Gestor, 2 personas Sindicalizados e 1 persona Advogada:

Como tem-se observado que o perfil de maior urg\u00eancia \u00e9 o de Gestor, outra persona Gestor deve ser constru\u00edda e enviada para valida\u00e7\u00e3o do cliente.

Foi observado tamb\u00e9m nessa reuni\u00e3o que h\u00e1 necessidade de maior participa\u00e7\u00e3o por parte dos estudantes de MDS. Assim, para incentivar essa colabora\u00e7\u00e3o, os MDS foram divididos em dois times pra cuidar de algumas demandas.

Time Respons\u00e1vel por guiar Participantes Demanda 1 Diogo Barboza Anna Brand\u00e3o, Jos\u00e9 Eduardo, Jo\u00e3o Victor Nobre Melhorar a persona gestor, criar outra persona gestor (especificar melhor as necessidades dessas 2 personas) e fazer as jornadas de usu\u00e1rio de cada um 2 Guilherme Storch Davi Nobre, Milena Rocha, Davi Mesquita Conferir se tudo que est\u00e1 no ENFN est\u00e1 representado no objetivos do produto e, se n\u00e3o estiver, adicionar em seu respectivo cluster; Jornadas das personas sindicalizadas e advogada

A ideia \u00e9 incentivar a colabora\u00e7\u00e3o entre os MDS que ainda n\u00e3o tiveram oportunidade de trabalhar juntos e aumentar a contribui\u00e7\u00e3o e o alinhamento do time, de forma que, os MDS se sintam mais inclu\u00eddos e seguros em participar da reuni\u00e3o com o cliente.

As atividades que foram pedidas deles devem ser acompanhadas pelos estudantes EPS dispon\u00edveis em caso de d\u00favida, e revisadas antes de serem enviadas para valida\u00e7\u00e3o do cliente.

"},{"location":"lean/dia3/#referencias","title":"Refer\u00eancias","text":"

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

"},{"location":"lean/dia3/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 09/04/24 Sara Campos"},{"location":"lean/dia4/","title":"Lean Inception - Dia 4","text":""},{"location":"lean/dia4/#jornadas-de-usuario","title":"Jornadas de Usu\u00e1rio","text":"

As Jornadas de Usu\u00e1rio s\u00e3o o passo a passo do que \u00e9 executado pela persona para cumprir um objetivo. Assim, s\u00e3o criados estes fluxos de atividades considerando o perfil, comportamento e as necessidades de cada persona..

"},{"location":"lean/dia4/#brainstorming-de-funcionalidades","title":"Brainstorming de funcionalidades","text":"

Para atender as necessidades das personas, as funcionalidades devem ser pensadas. Neste momento, a atividade requer que os participantes repassem pelos objetivos do produto e pelas jornadas para pensar de maneira mais modular em quais seriam as funcionalidades presentes no produto final enxuto.

"},{"location":"lean/dia4/#reuniao","title":"Reuni\u00e3o","text":"

Data: 15/04/24

Participantes:

Equipe Nomes PO Matheus Amaral, Davi Mendon\u00e7a EPS Ingrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio MDS Anna Brand\u00e3o, Guilherme Storch, Milena Rocha, Jos\u00e9 Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, Jo\u00e3o Victor Nobre

Descri\u00e7\u00e3o:

Como descrito no dia 3, os estudantes de MDS ficaram respons\u00e1veis por se organizar para realizar algumas atividades. Assim, os estudantes constru\u00edram as jornadas de usu\u00e1rio que posteriormente foram refinadas pelos estudantes de EPS. Al\u00e9m disso, duas novas personas foram criadas conforme foi identificado que era necess\u00e1rio.

Durante a reuni\u00e3o com os POs, foram apontadas algumas corre\u00e7\u00f5es que, por fim, resultaram nas seguintes personas e suas respectivas jornadas:

Persona 1 + Jornada:

Persona 2 + Jornada:

Persona 3 + Jornada:

Persona 4 + Jornada:

Persona 5 + Jornada:

Persona 6 + Jornada:

Com essa parte realizada, iniciamos nosso Brainstoming de Funcionalidades. Os resultados, no entanto, s\u00f3 foram alcan\u00e7ados no dia 5.

"},{"location":"lean/dia4/#referencias","title":"Refer\u00eancias","text":"

Journey Mapping 101 Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

"},{"location":"lean/dia4/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 15/04/24 Sara Campos Altera\u00e7\u00e3o do relato do dia 4 (12/04) para reuni\u00e3o com cliente (15/04) Sara Campos"},{"location":"lean/dia5/","title":"Lean Inception - Dia 5","text":""},{"location":"lean/dia5/#reuniao","title":"Reuni\u00e3o","text":"

Data: 17/04/24

Participantes:

Equipe Nomes PO Matheus Amaral, Davi Mendon\u00e7a EPS Ingrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio MDS Guilherme Storch, Jos\u00e9 Eduardo, Diogo Barboza, Davi Mesquita, Jo\u00e3o Victor Nobre

Descri\u00e7\u00e3o:

Nesta reuni\u00e3o, a proposta era finalizar o Brainstorming de Funcionalidades. As funcionalidades s\u00e3o representadas em post-its amarelos, enquanto em verde temos algumas notas que trazem detalhes a serem considerados sobre as respectivas funcionalidades.

O resultado mostrado nas imagens a seguir conta com altera\u00e7\u00f5es realizadas ap\u00f3s uma conversa no dia 19/04 com Lucas Neves, advogado representante da \u00e1rea jur\u00eddica do sindicato. Este encontro n\u00e3o foi considerado um dia de Lean Inception por sua breviedade (dura\u00e7\u00e3o de 15 minutos), mas ressalta-se que foi um momento importante que ajudou a confirmar e refinar as necessidades do jur\u00eddico anteriormente apontadas pelos POs Matheus e Davi.

"},{"location":"lean/dia5/#referencias","title":"Refer\u00eancias","text":"

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

"},{"location":"lean/dia5/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 23/04/24 Sara Campos"},{"location":"lean/dia6/","title":"Lean Inception - Dia 6","text":""},{"location":"lean/dia6/#revisao-tecnica-e-de-negocio","title":"Revis\u00e3o t\u00e9cnica e de neg\u00f3cio","text":"

Com as funcionalidades pensadas, chega a hora de classific\u00e1-las. O m\u00e9todo prop\u00f5e duas formas de classifica\u00e7\u00e3o:

  1. posicionando num gr\u00e1fico onde o eixo Y refere-se ao quanto a funcionalidade agrega valor ao produto, enquanto no eixo X qual seria a confian\u00e7a do time em executar a tarefa;
  2. conferindo ao post-it com a funcionalidade valor de esfor\u00e7o, valor de neg\u00f3cio e valor de UX.

Dessa forma, tem-se o seguinte formato de classifica\u00e7\u00e3o para os post-its:

"},{"location":"lean/dia6/#reuniao","title":"Reuni\u00e3o","text":"

Data: 22/04/24

Participantes:

Equipe Nomes PO Matheus Amaral, Davi Mendon\u00e7a EPS Ingrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio MDS Anna Brand\u00e3o, Guilherme Storch, Milena Rocha, Jos\u00e9 Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, Jo\u00e3o Victor Nobre

Descri\u00e7\u00e3o:

Para essa reuni\u00e3o, o grupo de estudantes havia se reunido logo antes para preparar a Revis\u00e3o T\u00e9cnica e de Neg\u00f3cio. Dessa forma, deixou-se para o momento agendado com o cliente apenas a defini\u00e7\u00e3o dos valores de neg\u00f3cio. Durante o encontro, a discuss\u00e3o sobre os valores de neg\u00f3cio de cada funcionalidade foi iniciada, mas a atribui\u00e7\u00e3o foi finalizada de modo ass\u00edncrono pelo PO Davi.

"},{"location":"lean/dia6/#referencias","title":"Refer\u00eancias","text":"

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

"},{"location":"lean/dia6/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 02/05/24 Sara Campos"},{"location":"lean/dia7/","title":"Lean Inception - Dia 7","text":""},{"location":"lean/dia7/#reuniao","title":"Reuni\u00e3o","text":"

Data: 22/04/24 - 15/07/24

Participantes:

Equipe Nomes PO Matheus Amaral, Davi Mendon\u00e7a EPS Ingrid Carvalho, Sara Campos, Alvaro Gouvea, Victor Yukio MDS Anna Brand\u00e3o, Guilherme Storch, Milena Rocha, Jos\u00e9 Eduardo, Diogo Barboza, Davi Mesquita, Davi Nobre, Jo\u00e3o Victor Nobre

Descri\u00e7\u00e3o:

No \u00faltimo dia, a inten\u00e7\u00e3o era construir o Sequenciador, artefato valioso para as estimativas de tempo e escopo do projeto. Seguindo as intru\u00e7\u00f5es de cria\u00e7\u00e3o do Sequenciador, as funcionalidades foram posicionadas nas raias e o MVP foi definido. Com isso, o time fez o Dimensionamento de Tarefas, que consiste em pegar amostras de raias com funcionalidades, detalhar em Hist\u00f3rias de Usu\u00e1rio, estimar o tamanho e o tempo de cada raia da amostra e assim chegar a uma m\u00e9dia de tempo por raia. Esse processo pode ser observado na figura abaixo.

Com o dimensionamento feito, o Sequenciador visto abaixo estava pronto para ser validado pelo cliente, o que foi feito de maneira remota.

Com o retorno das atividades ap\u00f3s o per\u00edodo de greves foi apresentado ao cliente o \u00faltimo artefato do Lean Inception, o Canvas MVP:

"},{"location":"lean/dia7/#referencias","title":"Refer\u00eancias","text":"

Lean Inception: Como alinhar pessoas e construir o produto certo. Caroli, Paulo.

"},{"location":"lean/dia7/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 02/05/24 Sara Campos Atualiza\u00e7\u00e3o 18/07/24 Sara Campos"},{"location":"prototipagem/idv/","title":"Identidade Visual","text":"

Na reuni\u00e3o com o cliente do dia 1\u00ba de abril foi apresentada e aprovada a nova identidade visual (IDV) do produto.

A nova IDV conta com uma paleta de cores selecionada trazendo identifica\u00e7\u00e3o para o SINDPOL, al\u00e9m passar mensagens de comprometimento, organiza\u00e7\u00e3o e eleg\u00e2ncia para o usu\u00e1rio. Foi realizado teste de contraste com a paleta de cores para validar a leiturabilidade para pessoas com daltonismo e outras defici\u00eancias que impactem a percep\u00e7\u00e3o das cores. Al\u00e9m disso, com a paleta de cores foram geradas 55 vari\u00e1veis de cores para serem usadas no prot\u00f3tipo mantendo a identidade visual.

Com rela\u00e7\u00e3o a tipografia, foram escolhidas duas fontes sem-serifa que passam modernidade e seriedade para o usu\u00e1rio ao interagir com o produto. As fontes cont\u00e9m tamb\u00e9m grande cobertura de caracteres e alta variabilidade de estilos, pesos e comprimentos. Os \u00edcones que devem ser usados no produto, seguindo a mesma ideia da tipografia, ser\u00e3o do pacote Ant Design Icons da biblioteca React Icons.

"},{"location":"prototipagem/idv/#proposta-de-identidade-visual-apresentada-e-aprovada","title":"Proposta de Identidade Visual apresentada e aprovada","text":""},{"location":"prototipagem/idv/#referencias","title":"Refer\u00eancias","text":"

Colormind.io Constrast Checker UI Colors Google Fonts - Noto Sans Google Fonts - Overpass React Icons - Ant Design Icons

"},{"location":"prototipagem/idv/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 02/04/24 Sara Campos Atualiza\u00e7\u00e3o 03/08/24 Sara Campos"},{"location":"prototipagem/prototipo/","title":"Prot\u00f3tipo de alta fidelidade","text":"

O time decidiu sempre desenvolver prot\u00f3tipos de alta fidelidade para o produto, utilizando da Identidade Visual e das discuss\u00f5es com os P.Os. Dessa forma, nas semanas inicias de desenvolvimento os EPS se encarregaram de prototipar as telas das US, mas logo foi realizado o Dojo de Figma e, assim, os MDS puderam tamb\u00e9m come\u00e7aram a trabalhar com prot\u00f3tipos.

Abaixo \u00e9 poss\u00edvel visualizar o prot\u00f3tipo naveg\u00e1vel, e o Figma onde tudo foi desenvolvido pode ser acessado tamb\u00e9m ao clicar aqui. Em todas as US foram anexados tamb\u00e9m links para os prot\u00f3tipos.

"},{"location":"prototipagem/prototipo/#historico-de-versoes","title":"Hist\u00f3rico de Vers\u00f5es","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"prototipagem/testesusabilidade/","title":"Testes de usabilidade","text":"

Ao longo do per\u00edodo letivo de 2024/1 ser\u00e3o realizados alguns testes de usabilidade com o cliente para entender melhor como o sistema pode se adequar \u00e0s necessidades dele e validar decis\u00f5es de design na prototipagem.

"},{"location":"prototipagem/testesusabilidade/#teste-de-usabilidade-1","title":"Teste de usabilidade 1","text":"

No intuito de compreender melhor o sistema e identificar poss\u00edveis melhorias, para o primeiro teste de usabilidade (realizado em 02 de abril) foi utilizado o prot\u00f3tipo naveg\u00e1vel constru\u00eddo no semestre 2023/2, como pode-se observar abaixo.

Algumas descobertas/possibilidades de melhoria identificadas no teste com o usu\u00e1rio:

  • \u00c9 necess\u00e1rio diferenciar login para os tipos de perfis (gestor/sindicalizado), neste prot\u00f3tipo os fluxos n\u00e3o diferenciam os tipos de permiss\u00e3o de cada perfil

  • O cliente v\u00ea urg\u00eancia no desenvolvimento do sistema com funcionalidades para o perfil de gestor

  • Formul\u00e1rio de filia\u00e7\u00e3o

  • O cliente disponibilizou arquivo com maiores instru\u00e7\u00f5es

  • Lembrete: dar sempre a op\u00e7\u00e3o de voltar para p\u00e1gina anterior

  • P\u00e1gina inicial ao logar no sistema

  • No sistema atual encontra-se um dashboard com estat\u00edsticas sobre os sindicalizados

  • Gerar documentos

  • Para o perfil de filiado/sindicalizado \u2192 emiss\u00e3o de carteirinha e declara\u00e7\u00e3o de v\u00ednculo

  • Para o perfil de gestor \u2192 inserir dados do sindicalizado e emitir os documentos

  • Desfilia\u00e7\u00e3o

  • Quando o usu\u00e1rio clica em configura\u00e7\u00f5es j\u00e1 abre direto nessa aba

  • Para o perfil de gestor \u2192 espera-se formul\u00e1rio conforme o requerimento que eles j\u00e1 usam atualmente e op\u00e7\u00e3o de gerar PDF para o sindicalizado assinar
  • Para o perfil de filiado \u2192 recebe PDF pra assinar e enviar de volta pro gestor como confirma\u00e7\u00e3o da desfilia\u00e7\u00e3o

  • Relat\u00f3rios

  • Sugest\u00e3o para validar com cliente: transformar em uma op\u00e7\u00e3o presente em todas as \u00e1reas pass\u00edveis de gerar relat\u00f3rio, desde o dashboard da p\u00e1gina inicial a outras funcionalidades

  • Patrim\u00f4nios

  • \u00c1rea de registro para controle do patrim\u00f4nio

  • Escala estado/conserva\u00e7\u00e3o n\u00e3o faz muito sentido, como mensurar?
    • Sugest\u00e3o para validar com cliente: colocar em forma de perguntas: tem defeitos funcionais? o uso \u00e9 afetado pela deprecia\u00e7\u00e3o? tem marcas de uso?
  • Material para doa\u00e7\u00e3o \u2192 registrar para onde foi
    • Sugest\u00e3o: checkbox no formul\u00e1rio de cadsastro do patrim\u00f4nio para informar se foi feita a doa\u00e7\u00e3o do patrim\u00f4nio, quando marcado abre outra part4e do formul\u00e1ria que registra para onde foi
  • Necessidade de uma listagem de patrim\u00f4nios (avaliar se \u00e9 necess\u00e1ria a op\u00e7\u00e3o de filtragem)
"},{"location":"prototipagem/testesusabilidade/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 03/04/24 Sara Campos Registro do teste de usabilidade 1 03/04/24 Sara Campos Atualiza\u00e7\u00e3o 03/08/24 Sara Campos"},{"location":"ritos/planning/","title":"Sprint Planning","text":""},{"location":"ritos/planning/#o-que-e-sprint-planning","title":"O que \u00e9 Sprint Planning?","text":"

A Sprint Planning \u00e9 uma reuni\u00e3o que d\u00e1 in\u00edcio a cada Sprint no framework Scrum. O principal objetivo dessa reuni\u00e3o \u00e9 definir o trabalho a ser realizado na pr\u00f3xima Sprint, criando um plano claro e compartilhado pela equipe de desenvolvimento. A Sprint Planning garante que todos os membros da equipe estejam alinhados quanto \u00e0s metas e tarefas a serem executadas, al\u00e9m de preparar o backlog da Sprint com as hist\u00f3rias e tarefas selecionadas.

"},{"location":"ritos/planning/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"
  • Definir o Objetivo da Sprint: Estabelecer uma meta clara e alcan\u00e7\u00e1vel que a equipe se compromete a atingir ao final da Sprint.
  • Selecionar Itens do Backlog do Produto: Escolher os itens de maior prioridade do backlog do produto que a equipe acredita ser capaz de completar durante a Sprint.
  • Criar o Backlog da Sprint: Dividir os itens selecionados em tarefas menores e mais gerenci\u00e1veis, criando um backlog da Sprint bem definido.
"},{"location":"ritos/planning/#participantes","title":"Participantes","text":"

1) Scrum Team: Inclui o Scrum Master, o Product Owner e a equipe de desenvolvimento.

"},{"location":"ritos/planning/#estrutura-da-sprint-planning","title":"Estrutura da Sprint Planning","text":"

A Sprint Planning geralmente \u00e9 dividida em duas partes principais:

"},{"location":"ritos/planning/#parte-1-o-que-sera-feito-na-sprint","title":"Parte 1: O que ser\u00e1 feito na Sprint?","text":"

Apresenta\u00e7\u00e3o dos Itens do Backlog do Produto: O Product Owner apresenta os itens de backlog mais priorit\u00e1rios e fornece o contexto necess\u00e1rio para a equipe.

Discuss\u00e3o dos Itens: A equipe de desenvolvimento faz perguntas e esclarece d\u00favidas sobre os itens apresentados, garantindo uma compreens\u00e3o completa das tarefas a serem realizadas.

Sele\u00e7\u00e3o dos Itens para a Sprint: Com base na prioridade e na capacidade da equipe, os itens do backlog s\u00e3o selecionados para a Sprint.

"},{"location":"ritos/planning/#parte-2-como-o-trabalho-sera-feito","title":"Parte 2: Como o trabalho ser\u00e1 feito?","text":"

Planejamento das Tarefas: Os itens selecionados s\u00e3o divididos em tarefas menores e detalhadas, que ser\u00e3o distribu\u00eddas entre os membros da equipe.

Estimativas de Tempo e Esfor\u00e7o: A equipe de desenvolvimento estima o tempo e o esfor\u00e7o necess\u00e1rios para completar cada tarefa, ajustando conforme necess\u00e1rio.

Cria\u00e7\u00e3o do Backlog da Sprint: Todas as tarefas planejadas s\u00e3o reunidas para formar o backlog da Sprint, com uma vis\u00e3o clara do que ser\u00e1 feito e como ser\u00e1 realizado.

"},{"location":"ritos/retrospective/","title":"Sprint Retrospectiva","text":""},{"location":"ritos/retrospective/#o-que-e-a-sprint-retrospectiva","title":"O que \u00e9 a Sprint Retrospectiva?","text":"

A Sprint Retrospectiva \u00e9 uma reuni\u00e3o realizada ao final de cada Sprint no framework Scrum. O objetivo principal dessa reuni\u00e3o \u00e9 permitir que a equipe Scrum reflita sobre o processo de trabalho utilizado durante a Sprint e identifique oportunidades de melhoria cont\u00ednua. \u00c9 um momento para a equipe avaliar o que funcionou bem, o que n\u00e3o funcionou e como os processos podem ser aprimorados para a pr\u00f3xima Sprint.

"},{"location":"ritos/retrospective/#objetivos-da-sprint-retrospectiva","title":"Objetivos da Sprint Retrospectiva","text":"

Refletir sobre a Sprint: Analisar como a Sprint transcorreu em termos de pessoas, rela\u00e7\u00f5es, processos e ferramentas. Identificar Melhorias: Destacar as \u00e1reas que precisam de melhorias e identificar a\u00e7\u00f5es concretas para implementar essas melhorias. Promover a Melhoria Cont\u00ednua: Desenvolver um plano de a\u00e7\u00e3o que a equipe possa seguir para aumentar a efici\u00eancia e a efic\u00e1cia nas pr\u00f3ximas Sprints.

"},{"location":"ritos/retrospective/#participantes","title":"Participantes","text":"

1) Scrum Team: Inclui o Scrum Master, o Product Owner e a equipe de desenvolvimento.

"},{"location":"ritos/retrospective/#estrutura-da-sprint-retrospectiva","title":"Estrutura da Sprint Retrospectiva","text":"

A Sprint Retrospectiva pode variar em formato e t\u00e9cnicas, mas geralmente inclui os seguintes elementos:

  1. Prepara\u00e7\u00e3o Ambiente Seguro: O Scrum Master cria um ambiente seguro e aberto onde todos se sintam confort\u00e1veis para compartilhar suas opini\u00f5es e ideias. Defini\u00e7\u00e3o da Agenda: O Scrum Master apresenta a agenda da reuni\u00e3o e define as expectativas.
  2. Reflex\u00e3o sobre a Sprint O que Funcionou Bem?: A equipe discute e anota os aspectos positivos da Sprint, identificando pr\u00e1ticas e processos que foram eficazes. O que N\u00e3o Funcionou?: A equipe analisa os desafios e problemas enfrentados durante a Sprint, discutindo os pontos que precisam ser melhorados.
  3. Identifica\u00e7\u00e3o de Melhorias Brainstorming: A equipe realiza uma sess\u00e3o de brainstorming para gerar ideias de melhorias. Priorizar Melhorias: As sugest\u00f5es de melhorias s\u00e3o priorizadas com base no impacto e na viabilidade.
  4. Desenvolvimento de um Plano de A\u00e7\u00e3o A\u00e7\u00f5es Concretas: A equipe define a\u00e7\u00f5es concretas e espec\u00edficas para implementar as melhorias identificadas. Respons\u00e1veis e Prazos: Cada a\u00e7\u00e3o recebe um respons\u00e1vel e um prazo para implementa\u00e7\u00e3o, garantindo que as melhorias sejam acompanhadas e realizadas.
  5. Fechamento Revis\u00e3o Final: A equipe revisa o plano de a\u00e7\u00e3o e garante que todos estejam alinhados e comprometidos. Agradecimentos: O Scrum Master agradece a participa\u00e7\u00e3o de todos e encerra a reuni\u00e3o.
"},{"location":"ritos/review/","title":"Sprint Review","text":""},{"location":"ritos/review/#o-que-e-sprint-review","title":"O que \u00e9 Sprint Review?","text":"

A Sprint Review \u00e9 um evento fundamental no Scrum, uma das metodologias \u00e1geis mais populares. Acontece ao final de cada Sprint, que \u00e9 um ciclo de desenvolvimento com dura\u00e7\u00e3o fixa (geralmente de duas a quatro semanas). O objetivo principal da Sprint Review \u00e9 inspecionar o incremento do produto e adaptar o backlog do produto conforme necess\u00e1rio.

"},{"location":"ritos/review/#objetivos-da-sprint-review","title":"Objetivos da Sprint Review","text":"
  • Inspecionar o Incremento: Avaliar o trabalho conclu\u00eddo durante a Sprint. O incremento \u00e9 a soma de todos os itens do backlog do produto completados durante a Sprint, que s\u00e3o potencialmente entreg\u00e1veis e prontos para uso.

  • Receber Feedback: Permitir que o Product Owner e os stakeholders forne\u00e7am feedback sobre o incremento, possibilitando ajustes e alinhamentos com as expectativas do cliente.

8 Adaptar o Backlog do Produto: Com base no feedback recebido e na inspe\u00e7\u00e3o do incremento, ajustar e priorizar o backlog do produto, preparando-o para a pr\u00f3xima Sprint.

"},{"location":"ritos/review/#participantes","title":"Participantes","text":"

1) Scrum Team: Inclui o Scrum Master, o Product Owner e a equipe de desenvolvimento.

2) Stakeholders: Clientes, usu\u00e1rios finais, gerentes e outros interessados no desenvolvimento do produto.

"},{"location":"ritos/review/#estrutura-da-sprint-review","title":"Estrutura da Sprint Review","text":"

A Sprint Review segue um formato estruturado, incluindo as seguintes etapas:

1) Apresenta\u00e7\u00e3o do Incremento: A equipe de desenvolvimento demonstra o trabalho conclu\u00eddo. Isso pode incluir uma demonstra\u00e7\u00e3o de novas funcionalidades, melhorias e corre\u00e7\u00f5es.

2) Discuss\u00e3o sobre o Produto: O Product Owner discute o estado atual do backlog do produto e o progresso em dire\u00e7\u00e3o \u00e0 meta do produto.

3) Feedback dos Stakeholders: Os stakeholders fornecem feedback sobre o incremento. Este \u00e9 um momento crucial para garantir que o desenvolvimento do produto esteja alinhado com as necessidades e expectativas dos usu\u00e1rios.

4) Revis\u00e3o e Adapta\u00e7\u00e3o do Backlog: Com base no feedback, o backlog do produto \u00e9 atualizado. Novas hist\u00f3rias podem ser adicionadas, e a prioriza\u00e7\u00e3o pode ser ajustada para refletir as mudan\u00e7as nas necessidades do neg\u00f3cio. Qualquer d\u00e9bito t\u00e9cnico ser\u00e1 discutido e ganhar\u00e1 destaque para o planejamento da pr\u00f3xima sprint.

5) Planejamento para a Pr\u00f3xima Sprint: Embora o foco principal da Sprint Review n\u00e3o seja o planejamento da pr\u00f3xima Sprint, algumas discuss\u00f5es preliminares podem ocorrer, preparando o terreno para a Sprint Planning.

"},{"location":"ritos/sprints/inicio/retomada_inicio/","title":"Retrospectiva de retomada de atividades","text":"

Com a retomada das atividades ap\u00f3s o per\u00edodo de greve, foi feita uma retrospectiva em sala aula com as turmas de EPS e MDS que resultou em tr\u00eas reflex\u00f5es principais.

1) Dificuldade de comunicar com o cliente.

2) Hor\u00e1rio das agendas.

3) Updates de EPS para mds.

As tr\u00eas principais dores do time foram encaminhadas nas atividades seguintes. A comunica\u00e7\u00e3o com o clinente apresentou melhora, assim como com o time, al\u00e9m da agenda, participa\u00e7\u00e3o e uni\u00e3o dos membros ter aumentado notavelmente.

"},{"location":"ritos/sprints/inicio/retomada_inicio/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 15/07/24 Victor Yukio Revis\u00e3o 18/07/24 Sara Campos"},{"location":"ritos/sprints/inicio/retrospec_inicio/","title":"Retrospectiva inicial","text":"

Nos dias iniciais da Sprint 1 foi realizada uma retrospectiva de maneira remota que gerou algumas reflex\u00f5es.

"},{"location":"ritos/sprints/inicio/retrospec_inicio/#pontos-positivos-e-negativos","title":"Pontos positivos e negativos","text":"

Na coluna \"Estrelas da Retro\" foram colocados os cards que tiveram mais reconhecimento do time, dos quais alguns foram encaminhados (como a planilha de datas provas, para melhorar o monitoramento de disponiblidade assim como de riscos), e outros (como comportamentos gerais do time) esperam ser mantidos.

"},{"location":"ritos/sprints/inicio/retrospec_inicio/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 15/07/24 Victor Yukio Revis\u00e3o 18/07/24 Sara Campos"},{"location":"ritos/sprints/sprint1/pareamentos1/","title":"Pareamentos","text":"

Na Sprint 1, ocorreram quatro pareamentos, de forma que todos participantes de MDS foram alocados em uma das US. Para a US01, foi definido um Squad respons\u00e1vel, que dividiu a tarefa na prepara\u00e7\u00e3o dos ambientes de frontend e backend, assim como o c\u00f3digo fonte da US em quest\u00e3o. As aloca\u00e7\u00f5es podem ser observadas nas tabelas abaixo:

Squad US Descri\u00e7\u00e3o \u00c1lvaro, Ingrid, Sara e Victor US01 Fazer login Pareamento US Descri\u00e7\u00e3o Guilherme e Milena US02 Solicitar filia\u00e7\u00e3o Anna e Davi Mesquita US03 Cadastrar fornecedores Davi Nobre e Jo\u00e3o Victor Nobre US04 Cadastrar usu\u00e1rios Diogo e Jos\u00e9 Eduardo US33 Atualizar dados do perfil"},{"location":"ritos/sprints/sprint1/pareamentos1/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 06/08/24 Sara Campos"},{"location":"ritos/sprints/sprint1/planning1/","title":"Sprint 1","text":""},{"location":"ritos/sprints/sprint1/planning1/#planning","title":"Planning","text":"

Data: 12/07/24

"},{"location":"ritos/sprints/sprint1/planning1/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 1, foram selecionadas hist\u00f3rias de usu\u00e1rio do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time com foco na entrega da Release 1, que se daria em duas sprints. Das seis hist\u00f3rias de usu\u00e1rio esperadas para entrega na Release 1, cinco foram distribu\u00eddas j\u00e1 na Sprint 1 conforme os pareamentos definidos.

"},{"location":"ritos/sprints/sprint1/planning1/#estrutura-da-sprint-planning","title":"Estrutura da Sprint Planning","text":"

As hist\u00f3rias de usu\u00e1rio definidas pro sprint backlog foram:

  • US01 - Fazer login
  • US02 - Solicitar filia\u00e7\u00e3o
  • US03 - Cadastrar fornecedores
  • US04 - Cadastrar usu\u00e1rios
  • US33 - Atualizar dados do usu\u00e1rio como sindicalizado

Nessa reuni\u00e3o foram especificados os crit\u00e9rios de aceita\u00e7\u00e3o de cada uma das seis US da Release 1 e cada uma foi encaminhada para prototipagem. A US01 (Fazer login) teve um caminho diferente, pois foi uma User Storie que viabilizou a prepara\u00e7\u00e3o de ambiente e in\u00edcio do c\u00f3dgio fonte, portanto esta j\u00e1 havia sido preparada antes da planning.

Al\u00e9m dos crit\u00e9rios de aceita\u00e7\u00e3o e prot\u00f3tipos, foram definidos os pontos por hist\u00f3ria de cada US, utilizando uma ferramenta online para o Planning Poker. Ao fim, foram estabelecidos os pareamentos que deveriam trabalhar em cada US durante a sprint que se iniciaria.

Com o que foi definido na reuni\u00e3o de planning e os prot\u00f3tipos concebidos nos dias que se seguiram, foi poss\u00edvel validar as US com os POs e, por fim, iniciar o desenvolvimento do c\u00f3digo fonte.

"},{"location":"ritos/sprints/sprint1/planning1/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 06/08/24 Sara Campos"},{"location":"ritos/sprints/sprint1/review1/","title":"Review","text":""},{"location":"ritos/sprints/sprint1/review1/#review","title":"Review","text":"

Data: 22/07/24

"},{"location":"ritos/sprints/sprint1/review1/#estrutura-da-sprint-review","title":"Estrutura da Sprint Review","text":"

Junto dos POs, foram tiradas d\u00favidas sobre o desenvolvimento e definidas pr\u00e1ticas de escrita mais detalhada das US e de comunica\u00e7\u00e3o com os POs. Sobre a US01 foram esclarecidos detalhes de como estava sendo feita a autentica\u00e7\u00e3o e ficou acordado que os POs enviariam o texto modelo pro e-mail que o usu\u00e1rio recebe na recupera\u00e7\u00e3o de senha. Os respons\u00e1veis pelas outras US tamb\u00e9m apresentaram o andamento do trabalho.

Houve a apresenta\u00e7\u00e3o das datas das releases pro cliente com o Canvas MVP e o Roadmap. Foram tamb\u00e9m colocadas para valida\u00e7\u00e3o as US da Sprint 3. Foi definido nesta reuni\u00e3o que a apresenta\u00e7\u00e3o da Releasse 1 ocorreria no dia 30/07/24 \u00e0s 20h.

"},{"location":"ritos/sprints/sprint1/review1/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint2/pareamentos2/","title":"Pareamentos","text":"

Na Sprint 2, ocorreram tamb\u00e9m quatro pareamentos, de forma que todos participantes de MDS foram alocados em pelo menos uma das US. Nessa Sprint os estudantes de EPS se encarregaram de auxiliar nas US necess\u00e1rias e de outras responsabilidades, como documenta\u00e7\u00f5es e DevOps. As aloca\u00e7\u00f5es podem ser observadas nas tabelas abaixo:

Pareamento US Descri\u00e7\u00e3o Guilherme e Milena US02 Solicitar filia\u00e7\u00e3o Guilherme e Milena US05 Cadastrar contas banc\u00e1rias Anna e Davi Mesquita US03 Cadastrar fornecedores Davi Nobre e Jo\u00e3o Victor Nobre US04 Cadastrar usu\u00e1rios Diogo e Jos\u00e9 Eduardo US33 Atualizar dados do perfil"},{"location":"ritos/sprints/sprint2/pareamentos2/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 06/08/24 Sara Campos"},{"location":"ritos/sprints/sprint2/planning2/","title":"Sprint 2","text":""},{"location":"ritos/sprints/sprint2/planning2/#planning","title":"Planning","text":"

Data: 19/07/24

"},{"location":"ritos/sprints/sprint2/planning2/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 2, foram selecionadas hist\u00f3rias de usu\u00e1rio do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time com foco na entrega da Release 1, que se daria ao fim dessa sprint. Das seis hist\u00f3rias de usu\u00e1rio esperadas para entrega na Release 1, apenas uma nova foi colocada no Sprint Backlog. Todos os pareamentos ainda estavam trabalhando nas US definidas anteriormente, mesmo que fossem pequenas finaliza\u00e7\u00f5es.

"},{"location":"ritos/sprints/sprint2/planning2/#estrutura-da-sprint-planning","title":"Estrutura da Sprint Planning","text":"

As hist\u00f3rias de usu\u00e1rio definidas pro sprint backlog foram:

  • US01 - Fazer login
  • US02 - Solicitar filia\u00e7\u00e3o
  • US03 - Cadastrar fornecedores
  • US04 - Cadastrar usu\u00e1rios
  • US33 - Atualizar dados do usu\u00e1rio como sindicalizado
  • US05 - Cadastrar contas banc\u00e1rias

Nessa reuni\u00e3o os estados de cada US foi alinhado entre todos os integrantes, foram mantidos os pareamentos anteriores e definido um pareamento que parecia mais pr\u00f3ximo de finalizar as tarefas da Sprint 1 para assumir a US05 assim que poss\u00edvel.

Foram especificadas tamb\u00e9m as US previstas pra Sprint 3, a fim de ter valida\u00e7\u00e3o dos POs com anteced\u00eancia.

"},{"location":"ritos/sprints/sprint2/planning2/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 06/08/24 Sara Campos"},{"location":"ritos/sprints/sprint2/retrospectiva/","title":"Retrospectiva da Release 1","text":""},{"location":"ritos/sprints/sprint2/retrospectiva/#pontos-positivos-e-negativos","title":"Pontos positivos e negativos","text":"

Foi bem: muito aprendizado e produtividade dos MDS, apoio dos EPS, intera\u00e7\u00e3o e comprometimento do grupo

Deu errado: estimativas de tempo para entrega e conhecimento raso sobre as tecnologias

Li\u00e7\u00f5es aprendidas: iniciar a sprint com tudo j\u00e1 validado e estimar melhor o tempo da sprint pensando em desenvolvimento e testes

"},{"location":"ritos/sprints/sprint2/retrospectiva/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint2/review2/","title":"Review","text":""},{"location":"ritos/sprints/sprint2/review2/#review","title":"Review","text":"

Data: 22/07/24 Facilitadora: Ingrid Respons\u00e1veis pela ata: Milena e Guilherme

"},{"location":"ritos/sprints/sprint2/review2/#estrutura-da-sprint-review","title":"Estrutura da Sprint Review","text":"

Como encaminhamento da Release 1, o time escolheu iniciar uma pr\u00e1tica de ter um facilitador EPS a cada semana na reuni\u00e3o com PO, ao passo que dois estudantes de MDS devem ficar respons\u00e1veis por anota\u00e7\u00f5es da reuni\u00e3o.

"},{"location":"ritos/sprints/sprint2/review2/#participantes","title":"Participantes:","text":"
  • Alvaro Henrique de Sousa Gouveaa
  • Anna Clara Cardoso Evangelista
  • Davi Dos Santos Brito
  • Diogo Rodrigues Barboza
  • Guilherme Storch De Oliveira
  • Ingrid da Silva Carvalho
  • Jo\u00e3o Victor Carvalho Nobre
  • Jose Eduardo Vieira Do Prado
  • Milena Fernandes Rocha
  • Sara Paula Lima Campos
  • Victor Yukio Cavalcanti
  • Davi Mendon\u00e7a
  • Matheus Amaral
"},{"location":"ritos/sprints/sprint2/review2/#pauta","title":"Pauta:","text":"
  • Revisar as US finalizadas e em andamento.
  • Validar os crit\u00e9rios de aceita\u00e7\u00e3o das poss\u00edveis US para a Sprint 4.
"},{"location":"ritos/sprints/sprint2/review2/#observacoes","title":"Observa\u00e7\u00f5es","text":"

Os PO\u2019s do projeto foram atualizados sobre as US\u2019s em andamento. Foi apresentado os crit\u00e9rios de aceita\u00e7\u00e3o das hist\u00f3rias de usu\u00e1rio candidatas para a Sprint 4.

  • US-16: Houve apresenta\u00e7\u00e3o dos crit\u00e9rios de aceita\u00e7\u00e3o da User Story;
  • US-20: Houve complementa\u00e7\u00e3o dos crit\u00e9rios de aceita\u00e7\u00e3o; nessa US, haver\u00e1 a necessidade de colocar o saldo do in\u00edcio e do final do m\u00eas.
  • US-21: Houve apresenta\u00e7\u00e3o dos crit\u00e9rios de aceita\u00e7\u00e3o da User Story e confirma\u00e7\u00e3o do que foi levantado pelo grupo por parte do PO;
  • US-22: Houve complementa\u00e7\u00e3o dos crit\u00e9rios de aceita\u00e7\u00e3o
"},{"location":"ritos/sprints/sprint2/review2/#decisoes","title":"Decis\u00f5es","text":"
  • Haver\u00e1 revis\u00e3o e complementa\u00e7\u00e3o dos crit\u00e9rios de aceita\u00e7\u00e3o pelo Mendon\u00e7a da US-16. Data limite estipulada: 06/08/2024.
  • Haver\u00e1 complementa\u00e7\u00e3o dos crit\u00e9rios de aceita\u00e7\u00e3o da US-22 - restri\u00e7\u00f5es do usu\u00e1rio sindicalizado.
"},{"location":"ritos/sprints/sprint2/review2/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Guilherme, Milena e Sara"},{"location":"ritos/sprints/sprint3/pareamentos3/","title":"Pareamentos","text":"

Na Sprint 3, ocorreram tamb\u00e9m tr\u00eas pareamentos, de forma que todos participantes de MDS foram alocados em uma das US. Nessa Sprint os estudantes de EPS se encarregaram de auxiliar nas US necess\u00e1rias, na realiza\u00e7\u00e3o dos testes e de outras responsabilidades, como documenta\u00e7\u00f5es e DevOps. As aloca\u00e7\u00f5es podem ser observadas nas tabelas abaixo:

Pareamento US Descri\u00e7\u00e3o Guilherme e Milena US34 Gerenciar filia\u00e7\u00f5es Anna, Diogo e Jos\u00e9 Eduardo US19 Cadastrar benef\u00edcios e conv\u00eanios Davi Nobre, Davi Mesquita e Jo\u00e3o Victor Nobre US17 Cadastrar perfis com permiss\u00f5es"},{"location":"ritos/sprints/sprint3/pareamentos3/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 06/08/24 Sara Campos"},{"location":"ritos/sprints/sprint3/planning3/","title":"Sprint 3","text":""},{"location":"ritos/sprints/sprint3/planning3/#planning","title":"Planning","text":"

Data: 26/07/24

"},{"location":"ritos/sprints/sprint3/planning3/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 3, foram selecionadas hist\u00f3rias de usu\u00e1rio do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribu\u00eddas tr\u00eas hist\u00f3rias de usu\u00e1rio conforme os pareamentos definidos.

"},{"location":"ritos/sprints/sprint3/planning3/#estrutura-da-sprint-planning","title":"Estrutura da Sprint Planning","text":"

As hist\u00f3rias de usu\u00e1rio definidas pro sprint backlog foram:

  • US34 - Gerenciar filia\u00e7\u00f5es
  • US19 - Cadastrar benef\u00edcios e conv\u00eanios
  • US17 - Cadastrar perfis com permiss\u00f5es no sistema

Como j\u00e1 haviam sido especificados e validados os crit\u00e9rios de aceita\u00e7\u00e3o e prot\u00f3tiops de cada uma das US de forma ass\u00edncrona, foram definidos os pareamentos respons\u00e1veis por cada uma.

Al\u00e9m dos crit\u00e9rios de aceita\u00e7\u00e3o e prot\u00f3tipos, foram definidos os pontos por hist\u00f3ria de cada US, utilizando uma ferramenta online para o Planning Poker.

Algumas US da Sprint 2 seguiram sendo finalizadas nos dias seguintes, como foco na entrega da Release 1, que se daria no dia 29/07/24. As US puxadas para o Backlog da Sprint 3 foram iniciadas conforme as US da Release 1 foram finalizadas.

Ap\u00f3s a apresenta\u00e7\u00e3o da Release 1, em 30/07/24, os participantes tamb\u00e9m se encarregaram de dar continuidade aos encaminhamentos apontados pelo professor, tanto de documenta\u00e7\u00e3o quanto de DevOps.

Nessa sprint tamb\u00e9m ficou definida uma mudan\u00e7a nas datas de review e planning para se adequar \u00e0 data de reuni\u00e3o com cliente e melhorar o fluxo de trabalho do grupo. Dessa forma, a sprint n\u00e3o foi finalizada, como seria esperado, no dia 02/08/24, mas no dia 05/08/24, quando ocorreu a review da Sprint 3 e a Planning da Sprint 4.

"},{"location":"ritos/sprints/sprint3/planning3/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 06/08/24 Guilherme, Milena e Sara"},{"location":"ritos/sprints/sprint3/retrospectiva/","title":"Retrospectiva 29/07","text":""},{"location":"ritos/sprints/sprint3/retrospectiva/#pontos-positivos-e-negativos","title":"Pontos positivos e negativos","text":"

Coisas boas: conduta e apoio dos EPS, conhecimento e ritmo de trabalho do MDS e valida\u00e7\u00f5es de US.

Coisas ruins: problemas referentes ambiente, volume de trabalho e erros cometidos.

"},{"location":"ritos/sprints/sprint3/retrospectiva/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint3/review3/","title":"Review","text":""},{"location":"ritos/sprints/sprint3/review3/#review","title":"Review","text":"

Data: 05/08/24 Facilitador: Alvaro Respons\u00e1veis pela ata: Anna e Guilherme

"},{"location":"ritos/sprints/sprint3/review3/#participantes","title":"Participantes:","text":"
  • Alvaro Henrique de Sousa Gouveaa
  • Anna Clara Cardoso Evangelista
  • Davi Dos Santos Brito
  • Diogo Rodrigues Barboza
  • Guilherme Storch De Oliveira
  • Ingrid da Silva Carvalho
  • Jo\u00e3o Victor Carvalho Nobre
  • Jose Eduardo Vieira Do Prado
  • Milena Fernandes Rocha
  • Sara Paula Lima Campos
  • Matheus Amaral
"},{"location":"ritos/sprints/sprint3/review3/#pauta","title":"Pauta:","text":"

Alinhamento sobre o roadmap do projeto; Valida\u00e7\u00e3o dos prot\u00f3tipos das US\u2019s: 21, 22, 23, 24. Valida\u00e7\u00e3o das Us\u2019s para a pr\u00f3xima release: 19, 02,

"},{"location":"ritos/sprints/sprint3/review3/#observacoes","title":"Observa\u00e7\u00f5es","text":"

Foram validadas as US\u2019s 21, 22, 23, com algumas ressalvas em seus respectivos prot\u00f3tipos; A US 21 - gerar relat\u00f3rio financeiro - N\u00e3o possui crit\u00e9rios de aceita\u00e7\u00e3o claros; foi alinhado com o P.O. a respeito das sua especificidade. Ser\u00e1 feito um ajuste no prot\u00f3tipo para futura valida\u00e7\u00e3o; Na US 22 - acessar presta\u00e7\u00e3o de contas do sindicato, o P.O. sugeriu inserir na view do sindicalizado uma label com o valor gasto para cada movimenta\u00e7\u00e3o do sindicato, bem como um filtro de pesquisa de cada um dos valores gastos pelo sindicato. Ser\u00e3o trocadas as labels \u201cSaldo inicial\u201d e \u201cSaldo final\u201d para \u201centrada\u201d e \u201csa\u00edda\u201d. Ser\u00e1 feito um ajuste no prot\u00f3tipo para futura valida\u00e7\u00e3o; Na US 23 - Consulta do hist\u00f3rico de contribui\u00e7\u00e3o do sindicalizado, o P.O. sugeriu inserir na view uma label com o valor gasto para cada contribui\u00e7\u00e3o do sindicalizado, bem como o valor total no intervalo selecionado na filtragem. Existem 4 tipos de contribui\u00e7\u00e3o. Ser\u00e1 feito um ajuste no prot\u00f3tipo para futura valida\u00e7\u00e3o; Na US 24 - Acessar hist\u00f3rico de contribui\u00e7\u00e3o como sindicalizado, o P.O. sugeriu inserir na view do sindicalizado uma busca com range de data por in\u00edcio e fim; valem as observa\u00e7\u00f5es para a US 23.

"},{"location":"ritos/sprints/sprint3/review3/#decisoes","title":"Decis\u00f5es","text":"

Ser\u00e1 validado pelo time a viabilidade de inserir um gr\u00e1fico de pizza na view da US 22; As US\u2019s 23 e 24 ser\u00e3o unificadas, diferenciando-se apenas pela regra de neg\u00f3cio do perfil de usu\u00e1rios: gestor e sindicalizado. Foram apresentadas as US\u2019s 02 e 19. Ap\u00f3s o deploy, o PO ir\u00e1 verificar e fazer os testes de aceita\u00e7\u00e3o.

"},{"location":"ritos/sprints/sprint3/review3/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Guilherme, Anna e Sara"},{"location":"ritos/sprints/sprint4/pareamentos4/","title":"Pareamentos","text":"

Na Sprint 4, foram definidos dois pareamentos. Nessa Sprint, ficou definido um novo padr\u00e3o de pareamentos, conforme notou-se necess\u00e1rio no fluxo de trabalho das semanas anteriores. As US portanto contar\u00e3o sempre com dois MDS acompanhados de um EPS. Foram puxadas para o Sprint Backlog duas hist\u00f3rias de usu\u00e1rio, para que os outros estudantes pudessem finalizar suas US em andamento e EPS se encarregassem de auxiliar nas US necess\u00e1rias e no aumento da cobertura de testes das US anteriores. As aloca\u00e7\u00f5es podem ser observadas nas tabelas abaixo:

Pareamento US Descri\u00e7\u00e3o Guilherme, Jo\u00e3o Victor e Victor US16 Visualizar dashboard sobre sindicalizados Davi Nobre, Davi Mesquita e Ingrid US20 Cadastrar movimenta\u00e7\u00f5es financeiras"},{"location":"ritos/sprints/sprint4/pareamentos4/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 06/08/24 Sara Campos"},{"location":"ritos/sprints/sprint4/planning4/","title":"Sprint 4","text":""},{"location":"ritos/sprints/sprint4/planning4/#planning","title":"Planning","text":"

Data: 05/08/24

"},{"location":"ritos/sprints/sprint4/planning4/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 4, foram selecionadas hist\u00f3rias de usu\u00e1rio do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribu\u00eddas duas novas hist\u00f3rias de usu\u00e1rio conforme os pareamentos definidos.

"},{"location":"ritos/sprints/sprint4/planning4/#estrutura-da-sprint-planning","title":"Estrutura da Sprint Planning","text":"

As hist\u00f3rias de usu\u00e1rio definidas pro sprint backlog foram:

  • US16 - Visualizar dashboard de informa\u00e7\u00f5es dos sindicalizados
  • US20 - Cadastrar movimenta\u00e7\u00f5es financeiras

Os crit\u00e9rios de aceita\u00e7\u00e3o e prot\u00f3tipos das duas US ficam para valida\u00e7\u00e3o de forma ass\u00edncrona e foram definidos os pareamentos respons\u00e1veis por cada uma.

Al\u00e9m dos crit\u00e9rios de aceita\u00e7\u00e3o e prot\u00f3tipos, foram definidos os pontos por hist\u00f3ria de cada US, utilizando uma ferramenta online para o Planning Poker.

Algumas US da Sprint 3 seguiram sendo finalizadas nos dias seguintes, como foco. As US puxadas para o Backlog da Sprint 4 devem ser iniciadas conforme as US da Sprint 3 forem finalizadas.

"},{"location":"ritos/sprints/sprint4/planning4/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 16/08/24 Guilherme, Anna e Sara"},{"location":"ritos/sprints/sprint4/retrospectiva/","title":"Retrospectiva 09/08","text":""},{"location":"ritos/sprints/sprint4/retrospectiva/#pontos-positivos-e-negativos","title":"Pontos positivos e negativos","text":"

Coisas boas: apoio dos EPS, ritmo de trabalho dos MDS e uma reuni\u00e3o de alinhamento realizada entre aulas com o time.

Coisas ruins: dificuldade de comunica\u00e7\u00e3o com cliente, atraso de valida\u00e7\u00f5es e volume de trabalho.

"},{"location":"ritos/sprints/sprint4/retrospectiva/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint4/review4/","title":"Review","text":""},{"location":"ritos/sprints/sprint4/review4/#review","title":"Review","text":"

Data: 12/08/24 Facilitador: Alvaro Respons\u00e1veis pela ata: Anna e Guilherme

"},{"location":"ritos/sprints/sprint4/review4/#participantes","title":"Participantes:","text":"
  • Alvaro Henrique de Sousa Gouveaa
  • Anna Clara Cardoso Evangelista
  • Davi Dos Santos Brito
  • Diogo Rodrigues Barboza
  • Guilherme Storch De Oliveira
  • Ingrid da Silva Carvalho
  • Jo\u00e3o Victor Carvalho Nobre
  • Jose Eduardo Vieira Do Prado
  • Milena Fernandes Rocha
  • Sara Paula Lima Campos
  • Matheus Amaral
"},{"location":"ritos/sprints/sprint4/review4/#pauta","title":"Pauta:","text":"

Alinhamento sobre o roadmap do projeto; Valida\u00e7\u00e3o dos prot\u00f3tipos das US\u2019s: 21, 22, 23, 24. Valida\u00e7\u00e3o das Us\u2019s para a pr\u00f3xima release: 19, 02,

"},{"location":"ritos/sprints/sprint4/review4/#observacoes","title":"Observa\u00e7\u00f5es","text":"

Foram validadas as US\u2019s 21, 22, 23, com algumas ressalvas em seus respectivos prot\u00f3tipos; A US 21 - gerar relat\u00f3rio financeiro - N\u00e3o possui crit\u00e9rios de aceita\u00e7\u00e3o claros; foi alinhado com o P.O. a respeito das sua especificidade. Ser\u00e1 feito um ajuste no prot\u00f3tipo para futura valida\u00e7\u00e3o; Na US 22 - acessar presta\u00e7\u00e3o de contas do sindicato, o P.O. sugeriu inserir na view do sindicalizado uma label com o valor gasto para cada movimenta\u00e7\u00e3o do sindicato, bem como um filtro de pesquisa de cada um dos valores gastos pelo sindicato. Ser\u00e3o trocadas as labels \u201cSaldo inicial\u201d e \u201cSaldo final\u201d para \u201centrada\u201d e \u201csa\u00edda\u201d. Ser\u00e1 feito um ajuste no prot\u00f3tipo para futura valida\u00e7\u00e3o; Na US 23 - Consulta do hist\u00f3rico de contribui\u00e7\u00e3o do sindicalizado, o P.O. sugeriu inserir na view uma label com o valor gasto para cada contribui\u00e7\u00e3o do sindicalizado, bem como o valor total no intervalo selecionado na filtragem. Existem 4 tipos de contribui\u00e7\u00e3o. Ser\u00e1 feito um ajuste no prot\u00f3tipo para futura valida\u00e7\u00e3o; Na US 24 - Acessar hist\u00f3rico de contribui\u00e7\u00e3o como sindicalizado, o P.O. sugeriu inserir na view do sindicalizado uma busca com range de data por in\u00edcio e fim; valem as observa\u00e7\u00f5es para a US 23.

"},{"location":"ritos/sprints/sprint4/review4/#decisoes","title":"Decis\u00f5es","text":"

Ser\u00e1 validado pelo time a viabilidade de inserir um gr\u00e1fico de pizza na view da US 22; As US\u2019s 23 e 24 ser\u00e3o unificadas, diferenciando-se apenas pela regra de neg\u00f3cio do perfil de usu\u00e1rios: gestor e sindicalizado. Foram apresentadas as US\u2019s 02 e 19. Ap\u00f3s o deploy, o PO ir\u00e1 verificar e fazer os testes de aceita\u00e7\u00e3o.

"},{"location":"ritos/sprints/sprint4/review4/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 16/08/24 Guilherme, Anna e Sara"},{"location":"ritos/sprints/sprint5/pareamentos5/","title":"Pareamentos","text":"

Na Sprint 5, as atividades foram separadas de forma a aliviar o gargalo de atividades que estavam nas suas fases finais (testes unit\u00e1rios e/ou testes de aceita\u00e7\u00e3o). Al\u00e9m disso, as US16 e US20 da Sprint 4 continuaram em progresso.

Pareamento US Descri\u00e7\u00e3o Sara Campos US19 Revis\u00e3o e testes unit\u00e1rios de Cadastro de benef\u00edcios Davi Nobre e Jos\u00e9 Eduardo US17 Testes unit\u00e1rios de Cadastro de perfis Davi Mesquita e Diogo US03 Testes unit\u00e1rios de Cadastro de fornecedores Milena US05 Testes unit\u00e1rios de Cadastro de contas banc\u00e1rias Guilherme, Jo\u00e3o Victor e Victor Yukio US16 Visualizar dashboard sobre sindicalizados Davi Nobre, Davi Mesquita e Ingrid US20 Cadastrar movimenta\u00e7\u00f5es financeiras"},{"location":"ritos/sprints/sprint5/pareamentos5/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint5/planning5/","title":"Sprint 5","text":""},{"location":"ritos/sprints/sprint5/planning5/#planningreview","title":"Planning/Review","text":"

Data: 12/08/24

"},{"location":"ritos/sprints/sprint5/planning5/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 5, ficou definido que n\u00e3o seriam iniciadas mais US, enquanto as US em andamento, em testes ou em aceita\u00e7\u00e3o ainda n\u00e3o estivessem finalizadas. Dessa forma, foi realizado um Dojo de Testes para aumentar o volume de pessoas trabalhando em finalizar todas as hist\u00f3rias de usu\u00e1rio. Como as US16 e US20 da Sprint 4 continuaram em andamento, os integrantes que n\u00e3o estavam nesses pareamentos da Sprint 4, foram divididos para aumentar a cobertura de testes das US que j\u00e1 estavam revisadas ou em testes de aceita\u00e7\u00e3o com usu\u00e1rio. Assim, foram definidos os pareamentos dessa sprint.

"},{"location":"ritos/sprints/sprint5/planning5/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 16/08/24 Sara Campos"},{"location":"ritos/sprints/sprint5/retrospectiva/","title":"Retrospectiva 12/08","text":""},{"location":"ritos/sprints/sprint5/retrospectiva/#pontos-positivos-e-negativos","title":"Pontos positivos e negativos","text":"

Coisas boas: apoio dos EPS, ritmo de trabalho dos MDS, integra\u00e7\u00e3o do time e US validadas.

Coisas ruins: press\u00e3o da reta final.

"},{"location":"ritos/sprints/sprint5/retrospectiva/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint5/review5/","title":"Review","text":""},{"location":"ritos/sprints/sprint5/review5/#review","title":"Review","text":"

Data: 19/08/24 Facilitador: Ingrid Respons\u00e1veis pela ata: Jo\u00e3o Victor e Davi Nobre

"},{"location":"ritos/sprints/sprint5/review5/#participantes","title":"Participantes:","text":"
  • Alvaro Henrique de Sousa Gouveaa
  • Anna Clara Cardoso Evangelista
  • Davi Dos Santos Brito
  • Diogo Rodrigues Barboza
  • Guilherme Storch De Oliveira
  • Ingrid da Silva Carvalho
  • Jo\u00e3o Victor Carvalho Nobre
  • Jose Eduardo Vieira Do Prado
  • Milena Fernandes Rocha
  • Sara Paula Lima Campos
  • Matheus Amaral
  • Davi Mendon\u00e7a
"},{"location":"ritos/sprints/sprint5/review5/#pauta","title":"Pauta:","text":"

Alinhamento sobre os retornos dos testes de aceita\u00e7\u00e3o; Atualiza\u00e7\u00e3o das US em andamento; Prepara\u00e7\u00e3o para release MVP.

"},{"location":"ritos/sprints/sprint5/review5/#observacoes","title":"Observa\u00e7\u00f5es","text":"

Nessa reuni\u00e3o foram esclarecidas d\u00favidas originadas da US16, por exemplo, Sexo era um campo n\u00e3o obrigat\u00f3rio, o que afetaria nas estat\u00edsitcas coletadas para o dashboard. Outro problema, era a lota\u00e7\u00e3o ser um campo livre, que dificultava a visualiza\u00e7\u00e3o dos sindicalizados entre lota\u00e7\u00f5es. Foi falado tamb\u00e9m sobre limpar a visualiza\u00e7\u00e3o dos HUBS.

"},{"location":"ritos/sprints/sprint5/review5/#decisoes","title":"Decis\u00f5es","text":"

Foram encaminhadas as altera\u00e7\u00f5es, de forma a deixar apenas bot\u00f5es de lista nos HUBS, visto que o cadastro pode ser acessado via lista. Al\u00e9m disso, surgiu uma nova hist\u00f3ria de usu\u00e1rio que foi priorizada para a Release MVP, na qual haveria um cadastro de \u00f3rg\u00e3o e, dentro do \u00f3rg\u00e3o, pudessem ser cadastradas as lota\u00e7\u00f5es que ficariam dispon\u00edveis para preenchimento no formul\u00e1rio de filia\u00e7\u00e3o.

"},{"location":"ritos/sprints/sprint5/review5/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Jo\u00e3o Victor, Davi Nobre e Sara"},{"location":"ritos/sprints/sprint6/pareamentos6/","title":"Pareamentos","text":"

Na Sprint 6, as atividades foram separadas de forma a entregar as atividades previstas para o MVP. Destas, a US21 e a US22 foram remanejadas e jogadas para sprint futura, a fim de finalizar com qualidade as US que j\u00e1 estavam priorizadas em andamento.

Pareamento US Descri\u00e7\u00e3o Jos\u00e9 Eduardo, Davi Nobre e Ingrid US23 Consulta do hist\u00f3rico de contribui\u00e7\u00e3o do sindicalizado Diogo, Milena e Sara US35 Cadastro de \u00f3rg\u00e3o lota\u00e7\u00e3o Anna US20 Testes"},{"location":"ritos/sprints/sprint6/pareamentos6/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint6/planning6/","title":"Sprint 6","text":""},{"location":"ritos/sprints/sprint6/planning6/#planning","title":"Planning","text":"

Data: 19/08/24

"},{"location":"ritos/sprints/sprint6/planning6/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 6, foram selecionadas hist\u00f3rias de usu\u00e1rio do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribu\u00eddas duas novas hist\u00f3rias de usu\u00e1rio conforme os pareamentos definidos. Nessa sprint, foi adicionada uma nova hist\u00f3ria de usu\u00e1rio ao Backlog do Produto, conforme necessidade identificada. Isso ocorreu por conta da US16, que diz respeito ao dashboard de estat\u00edticas sobre os sindicalizados, na qual notou-se que seria necess\u00e1rio haver um cadastro de \u00f3rg\u00e3os e lota\u00e7\u00f5es (instanciado na US35) para serem usados no cadastro de sindicalizado.

"},{"location":"ritos/sprints/sprint6/planning6/#estrutura-da-sprint-planning","title":"Estrutura da Sprint Planning","text":"

As hist\u00f3rias de usu\u00e1rio definidas pro sprint backlog foram:

  • US23 - Consulta do hist\u00f3rico de contribui\u00e7\u00e3o do sindicalizado
  • US35 - Cadastrar \u00f3rg\u00e3os

Os crit\u00e9rios de aceita\u00e7\u00e3o e prot\u00f3tipos j\u00e1 haviam sido validados anteriormente, exceto pela US35, que foi instanciada e ficou para valida\u00e7\u00e3o de forma ass\u00edncrona.

Al\u00e9m dos crit\u00e9rios de aceita\u00e7\u00e3o e prot\u00f3tipos, foram definidos os pontos por hist\u00f3ria de cada US, utilizando uma ferramenta online para o Planning Poker.

Algumas US da Sprint 5 seguiram sendo finalizadas nos dias seguintes, com foco na entrega da Release MVP.

"},{"location":"ritos/sprints/sprint6/planning6/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint6/review6/","title":"Review","text":""},{"location":"ritos/sprints/sprint6/review6/#reviewapresentacao-da-release-mvp","title":"Review/Apresenta\u00e7\u00e3o da Release MVP","text":"

Data: 26/08/24

"},{"location":"ritos/sprints/sprint6/review6/#participantes","title":"Participantes:","text":"
  • Alvaro Henrique de Sousa Gouveaa
  • Anna Clara Cardoso Evangelista
  • Davi Dos Santos Brito
  • Davi Mesquita
  • Diogo Rodrigues Barboza
  • Guilherme Storch De Oliveira
  • Ingrid da Silva Carvalho
  • Jo\u00e3o Victor Carvalho Nobre
  • Jose Eduardo Vieira Do Prado
  • Milena Fernandes Rocha
  • Sara Paula Lima Campos
  • Victor Yukio
  • Matheus Amaral
  • Davi Mendon\u00e7a
"},{"location":"ritos/sprints/sprint6/review6/#pauta","title":"Pauta:","text":"

Apresenta\u00e7\u00e3o das US do MVP; Atualiza\u00e7\u00e3o do documento de custos; Atualiza\u00e7\u00e3o do andamento do roadmap.

"},{"location":"ritos/sprints/sprint6/review6/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara"},{"location":"ritos/sprints/sprint7/pareamentos7/","title":"Pareamentos","text":"

Na Sprint 7, as atividades foram separadas de forma a corrigir as US do MVP para entrega da Release N. Al\u00e9m disso, foi puxada a US21 do backlog do produto.

Pareamento US Descri\u00e7\u00e3o Jos\u00e9 Eduardo, Davi Nobre e Sara US21 Gerar relat\u00f3rio de movimenta\u00e7\u00f5es financeiras Diogo e Jo\u00e3o Victor US17 Cadastrar perfis Diogo e Jo\u00e3o Victor US18 Atribuir perfis Milena e Guilherme ENH-US02 Evolu\u00e7\u00e3o adaptativa da US02 Milena e Guilherme ENH-US05 Evolu\u00e7\u00e3o corretiva da US05"},{"location":"ritos/sprints/sprint7/pareamentos7/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint7/planning7/","title":"Sprint 7","text":""},{"location":"ritos/sprints/sprint7/planning7/#planning","title":"Planning","text":"

Data: 26/08/24

"},{"location":"ritos/sprints/sprint7/planning7/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 7, foram selecionadas hist\u00f3rias de usu\u00e1rio do Backlog do Produto para o Sprint Backlog e divididas entre os integrantes do time. Foram distribu\u00eddas hist\u00f3rias de usu\u00e1rio conforme os pareamentos definidos. Al\u00e9m disso, nessa sprint foram iniciadas evolu\u00e7\u00f5es adaptativa e corretiva. Foi identificado que a US17 estava com crit\u00e9rios de aceita\u00e7\u00e3o incompletos, e a US18, que havia sido colocada na coluna Icebox do Zenhub, foi repriorizada e puxada para o sprint backlog.

"},{"location":"ritos/sprints/sprint7/planning7/#estrutura-da-sprint-planning","title":"Estrutura da Sprint Planning","text":"

As hist\u00f3rias de usu\u00e1rio definidas pro sprint backlog foram:

  • US21 - Gerar relat\u00f3rio de movimenta\u00e7\u00f5es financeiras
  • US17 - Cadastrar perfis
  • US18 - Atribuir perfis aos usu\u00e1rios
  • ENH-US02 - Evolu\u00e7\u00e3o adaptativa da US02
  • ENH-US05 - Evolu\u00e7\u00e3o corretiva da US05
"},{"location":"ritos/sprints/sprint7/planning7/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint7/retrospectiva/","title":"Retrospectiva 30/08","text":""},{"location":"ritos/sprints/sprint7/retrospectiva/#pontos-positivos-e-negativos","title":"Pontos positivos e negativos","text":"

Coisas boas: entrega do MVP, apoio dos EPS, boa cobertura de testes e a chegada da reta final.

Coisas ruins: cansa\u00e7o, dificuldade com CSS e problemas com husky.

"},{"location":"ritos/sprints/sprint7/retrospectiva/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint7/review7/","title":"Review","text":""},{"location":"ritos/sprints/sprint7/review7/#review","title":"Review","text":"

Data: 02/09/24 Facilitador: Sara

"},{"location":"ritos/sprints/sprint7/review7/#participantes","title":"Participantes:","text":"
  • Alvaro Henrique de Sousa Gouveaa
  • Anna Clara Cardoso Evangelista
  • Davi Dos Santos Brito
  • Davi Mesquita
  • Diogo Rodrigues Barboza
  • Guilherme Storch De Oliveira
  • Ingrid da Silva Carvalho
  • Jo\u00e3o Victor Carvalho Nobre
  • Jose Eduardo Vieira Do Prado
  • Milena Fernandes Rocha
  • Sara Paula Lima Campos
  • Matheus Amaral
  • Davi Mendon\u00e7a
"},{"location":"ritos/sprints/sprint7/review7/#pauta","title":"Pauta:","text":"

Apresenta\u00e7\u00e3o das atividades em andamento e alinhamento com os POs; Conversa sobre os pr\u00f3ximos passos ate a release N; Apresenta\u00e7\u00e3o do agile evm.

"},{"location":"ritos/sprints/sprint7/review7/#observacoes","title":"Observa\u00e7\u00f5es","text":"

Foi apontado que \u00e9 necess\u00e1rio rever a US de login de valida\u00e7\u00e3o do email, Matheus j\u00e1 aceitou por\u00e9m apenas com o v\u00eddeo. US20 - Prot\u00f3tipo e crit\u00e9rio estavam um pouco confuso , campos de aceita\u00e7\u00e3o campo de data na listagem dd/mm/yyy e drop down na hora da edi\u00e7\u00e3o de \u201ctipo documento\u201d US23 - observa\u00e7\u00e3o na us de concilia\u00e7\u00e3o de movimenta\u00e7\u00f5es Colocar um bot\u00e3o para o admin ver o perfil US03 - css olhar para campos uf de todas as telas principalmente de fornecedores resolver \u00f3rg\u00e3o e lota\u00e7\u00e3o US34 - email US21 e requisitos, validar csv e pdf- selecionar os campos (filtros) que ele quer, colocar bras\u00e3o do sindicato

"},{"location":"ritos/sprints/sprint7/review7/#decisoes","title":"Decis\u00f5es","text":"

Foram seguidas as corre\u00e7\u00f5es pedidas e feito o prot\u00f3tipo da US21 que ainda n\u00e3o havia sido validado. Al\u00e9m disso, a US22 foi despriorizada num acordo entre o time e os P.Os, a fim de priorizar a entrega de qualidade das US que j\u00e1 estavam encaminhadas.

"},{"location":"ritos/sprints/sprint7/review7/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara"},{"location":"ritos/sprints/sprint8/planning8/","title":"Sprint 7","text":""},{"location":"ritos/sprints/sprint8/planning8/#planning","title":"Planning","text":"

Data: 02/09/24

"},{"location":"ritos/sprints/sprint8/planning8/#objetivos-da-sprint-planning","title":"Objetivos da Sprint Planning","text":"

Para a Sprint 8, as US apenas foram contiuadas pelos seus respons\u00e1veis definidos nos pareamentos, com foco em finalizar uma entrega de qualidade para a Release N.

"},{"location":"ritos/sprints/sprint8/planning8/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/sprints/sprint8/retrospectiva/","title":"Retrospectiva da Release Final","text":""},{"location":"ritos/sprints/sprint8/retrospectiva/#pontos-positivos-e-negativos","title":"Pontos positivos e negativos","text":"

Coisas boas: entregas finalizadas, apoio dos EPS, trabalho dos MDS, evolu\u00e7\u00e3o pessoal, pareamentos presenciais e reconhecimento do professor.

Coisas ruins: cansa\u00e7o, bugs, tempo curto para apresentar a quantidade de coisas que foram feitas.

"},{"location":"ritos/sprints/sprint8/retrospectiva/#historico-de-versao","title":"Hist\u00f3rico de vers\u00e3o","text":"Altera\u00e7\u00e3o Data Autor Cria\u00e7\u00e3o do documento 08/09/24 Sara Campos"},{"location":"ritos/template/planning/","title":"Template Sprint Planning","text":""},{"location":"ritos/template/planning/#planejamento-sprint-x","title":"Planejamento Sprint X","text":""},{"location":"ritos/template/planning/#objetivos-da-sprint","title":"Objetivos da sprint","text":"
  • Objetivos da sprint
"},{"location":"ritos/template/planning/#tamanho-da-sprint","title":"Tamanho da Sprint","text":"
  • In\u00edcio: -/-/2024
  • T\u00e9rmino: -/-/2024
  • Dura\u00e7\u00e3o: - dias
"},{"location":"ritos/template/planning/#pareamentos","title":"Pareamentos","text":"
  • Documentar como foram escolhidos os pareamentos da sprint
  • Duplas escolhidas
"},{"location":"ritos/template/planning/#sprint-backlog","title":"Sprint Backlog","text":"
  • Tabela de issues escolhidas para a semana, pontua\u00e7\u00e3o e responsaveis
Issue Pontos Respons\u00e1veis Nome da issue - Nome da issue - Nome da issue - Nome da issue -"},{"location":"ritos/template/retrospec/","title":"Template Retrospectiva de Sprint","text":""},{"location":"ritos/template/retrospec/#analise-da-sprint","title":"An\u00e1lise da sprint","text":"
  • Fazer uma breve an\u00e1lise sobre os resultados obtidos ao fim da sprint
"},{"location":"ritos/template/retrospec/#pontos-positivos-e-negativos","title":"Pontos Positivos e Negativos","text":""},{"location":"ritos/template/review/","title":"Template Sprint Review","text":""},{"location":"ritos/template/review/#resultados-obtidos-na-sprint","title":"Resultados obtidos na sprint","text":"

Resultados obtidos na sprint.

"},{"location":"ritos/template/review/#reports","title":"Reports","text":""},{"location":"ritos/template/review/#tarefas-realizadas","title":"Tarefas Realizadas","text":"

Quadro que mostra quais tarefas planejadas foram conclui\u0301das.

Tarefa Pontuac\u0327a\u0303o Conclui\u0301da Tarefa concui\u0301da -- Tarefa na\u0303o conclui\u0301da --

"},{"location":"ritos/template/review/#burndown","title":"Burndown","text":"
  • Gra\u0301fico de Burndown da sprint(imagem)
"},{"location":"ritos/template/review/#velocity","title":"Velocity","text":"
  • Gra\u0301fico de Velocity da sprint(imagem)
"},{"location":"ritos/template/review/#conhecimento-dos-membros","title":"Conhecimento dos membros","text":"
  • Tabela de conhecimento da sprint(imagem).
"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..c31c05a --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,263 @@ + + + + https://documentacao-SENTINELA.com/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/conclusao/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/alinhamento/canais/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/alinhamento/disponibilidade/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/alinhamento/dojos/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/alinhamento/heatmap/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/arquitetura/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/backlog/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/ci-cd/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/custo/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/eap/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/evm/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/guia-de-contribuicao/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/manual-de-instalacao/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/melhorias-defeitos/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/metodologia/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/planoQualidade/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/riscos/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/gestao/roadmap/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/lean/dia1/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/lean/dia2/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/lean/dia3/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/lean/dia4/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/lean/dia5/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/lean/dia6/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/lean/dia7/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/prototipagem/idv/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/prototipagem/prototipo/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/prototipagem/testesusabilidade/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/planning/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/retrospective/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/review/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/inicio/retomada_inicio/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/inicio/retrospec_inicio/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint1/pareamentos1/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint1/planning1/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint1/review1/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint2/pareamentos2/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint2/planning2/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint2/retrospectiva/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint2/review2/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint3/pareamentos3/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint3/planning3/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint3/retrospectiva/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint3/review3/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint4/pareamentos4/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint4/planning4/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint4/retrospectiva/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint4/review4/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint5/pareamentos5/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint5/planning5/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint5/retrospectiva/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint5/review5/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint6/pareamentos6/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint6/planning6/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint6/review6/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint7/pareamentos7/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint7/planning7/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint7/retrospectiva/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint7/review7/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint8/planning8/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/sprints/sprint8/retrospectiva/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/template/planning/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/template/retrospec/ + 2024-09-14 + + + https://documentacao-SENTINELA.com/ritos/template/review/ + 2024-09-14 + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..13907ce Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/stylesheets/extra.css b/stylesheets/extra.css new file mode 100644 index 0000000..d87d122 --- /dev/null +++ b/stylesheets/extra.css @@ -0,0 +1,9 @@ +[data-md-color-scheme="slate"] { + --md-primary-fg-color: #83341D; + --md-primary-bg-color: #E2D4C6; +} + +[data-md-color-scheme="default"] { + --md-primary-fg-color: #2D1D1A; + --md-primary-bg-color: #AE883C; +} \ No newline at end of file

Tabela com os valores detalhados