├── .prettierrc
├── .gitignore
├── public
├── fplan.png
├── favicon.png
└── index.html
├── babel.config.js
├── .github
└── workflows
│ └── node.js.yml
├── src
├── useWindowSize.js
├── components
│ ├── CalendarWeek.js
│ ├── Body.js
│ ├── Calendar.js
│ ├── CalendarAgenda.js
│ ├── ManualUploadModal.js
│ ├── Sugerencias.js
│ ├── SelectExtra.js
│ ├── SelectMateria.js
│ ├── SelectCurso.js
│ ├── TabSystem.js
│ └── MateriasDrawer.js
├── theme.js
├── index.js
├── utils.js
├── siuparser.js
├── Style.css
└── DataContext.js
├── LICENSE
├── README.md
├── package.json
└── tests
├── siuparser.test.js
├── siu-json
├── siu-exactas-computacion-primer-cuatri.json
└── siu-axel.json
└── siu-raw
└── siu-exactas-computacion-primer-cuatri.js
/.prettierrc:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 | .ipynb_checkpoints
4 | .venv
5 |
--------------------------------------------------------------------------------
/public/fplan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FdelMazo/FIUBA-Plan/HEAD/public/fplan.png
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FdelMazo/FIUBA-Plan/HEAD/public/favicon.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@babel/preset-env',
4 | ['@babel/preset-react', {runtime: 'automatic'}],
5 | ],
6 | };
7 |
--------------------------------------------------------------------------------
/.github/workflows/node.js.yml:
--------------------------------------------------------------------------------
1 | name: Build & Deploy to Github Pages
2 |
3 | on:
4 | push:
5 | branches: [master]
6 |
7 | jobs:
8 | node-to-gh:
9 | runs-on: ubuntu-latest
10 | name: Build & Deploy to Github Pages
11 | steps:
12 | - id: node-to-gh
13 | uses: fdelmazo/node-to-gh-action@v2
14 | - name: Run tests
15 | run: npm test
16 | shell: bash
17 |
--------------------------------------------------------------------------------
/src/useWindowSize.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default function useWindowSize() {
4 | const [windowSize, setWindowSize] = React.useState({
5 | width: undefined,
6 | height: undefined,
7 | });
8 |
9 | React.useEffect(() => {
10 | function handleResize() {
11 | setWindowSize({
12 | width: window.innerWidth,
13 | height: window.innerHeight,
14 | });
15 | }
16 |
17 | window.addEventListener("resize", handleResize);
18 | handleResize();
19 |
20 | return () => window.removeEventListener("resize", handleResize);
21 | }, []);
22 |
23 | return windowSize;
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/CalendarWeek.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import TimeGrid from "react-big-calendar/lib/TimeGrid";
3 | import Week from "react-big-calendar/lib/Week";
4 | import WorkWeek from "react-big-calendar/lib/WorkWeek";
5 |
6 | class CalendarWeek extends WorkWeek {
7 | range(date, events, options) {
8 | const showSabado = !!events.find((e) => e.end.getDay() === 6);
9 | const DAYS = showSabado ? [1, 2, 3, 4, 5, 6] : [1, 2, 3, 4, 5];
10 | return Week.range(date, options).filter((d) => DAYS.includes(d.getDay()));
11 | }
12 |
13 | render() {
14 | let { date, ...props } = this.props;
15 | let events = this.props.events || [];
16 | let range = this.range(date, events, this.props);
17 |
18 | return ;
19 | }
20 | }
21 |
22 | export default CalendarWeek;
23 |
--------------------------------------------------------------------------------
/src/theme.js:
--------------------------------------------------------------------------------
1 | import { extendTheme } from "@chakra-ui/react";
2 | import "react-big-calendar/lib/css/react-big-calendar.css";
3 | import "./Style.css";
4 |
5 | const config = {
6 | initialColorMode: "system",
7 | };
8 |
9 | const customTheme = extendTheme({
10 | fonts: {
11 | body: "Source Sans Pro",
12 | heading: "Georgia, serif",
13 | mono: "Menlo, monospace",
14 | },
15 | colors: {
16 | primary: {
17 | 50: "#e5cff8",
18 | 100: "#dec4f7",
19 | 200: "#d8b8f6",
20 | 300: "#d2adf4",
21 | 400: "#cba2f3",
22 | 500: "#bf8cf0",
23 | 600: "#b881ee",
24 | 700: "#b275ed",
25 | 800: "#ac6aeb",
26 | 900: "#a55fea",
27 | },
28 | drawerbg: "#222d38",
29 | drawerbgdark: "#3c4042",
30 | drawerbgalpha: "#222d38CC",
31 | drawerbgdarkalpha: "#3c4042CC",
32 | agendabgdark: "#323f56",
33 | calendarbg: "#f7f9fa",
34 | calendarbgdark: "#222d38",
35 | calendarbggrey: "#ededed",
36 | hovercolor: "#e2e8f033",
37 | },
38 | config,
39 | });
40 |
41 | export default customTheme;
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Federico del Mazo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 | FIUBA Plan · fede.dm
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [FIUBA-Plan](https://fede.dm/FIUBA-Plan/)
2 |
3 | Organizador de horarios de la Facultad de Ingenieria
4 |
5 | ---
6 |
7 | 
8 |
9 | Este proyecto apunta a una manera más facil de visualizar los horarios de cursada de la FIUBA. La idea es que no dependa de ningun servicio externo para conseguir los horarios cada cuatrimestre (porque no existe ninguno confiable que sea actualizado año a año), y los horarios sean cargados manualmente por el usuario que los puede obtener de su SIU (incluso, en una de esas funciona para SIUs de otras facultades de la UBA).
10 |
11 | ## Desarrollo
12 |
13 | Para agregar un feature o fixear un issue hay que clonar el repositorio, instalar las dependencias con `npm install` y después correr la aplicación con `npm start`. En `localhost:3000/` va a estar corriendo la aplicación constantemente, y toda modificación que se haga al código se va a ver reflejada en la página.
14 |
15 | Con `npm test` se pueden correr los tests del parser del SIU, para agregar tests de distintos SIUs podés agregar en `siu-raw` el texto de tu SIU, y en `siu-json` el objeto que da el parser luego de procesar el texto del SIU que pegas en el cuadro de texto (en la consola de desarrollo se imprime).
16 |
17 | Una vez terminados los cambios, con solo hacer un PR basta (porque la aplicación se compila automáticamente con cada push a master).
18 |
19 | Si tenés algún problema con el parser podés armar un issue con lo que intentaste pegar en el cuadro de texto.
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fiuba-plan",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@chakra-ui/icons": "^2.0.19",
7 | "@chakra-ui/react": "^2.7.1",
8 | "@emotion/react": "^11.11.1",
9 | "@emotion/styled": "^11.11.0",
10 | "@fontsource/source-sans-pro": "^4.5.1",
11 | "buffer": "^6.0.3",
12 | "color-hash": "^2.0.2",
13 | "downshift": "^8.5.0",
14 | "framer-motion": "^6.5.1",
15 | "immer": "^10.0.2",
16 | "moment": "^2.29.4",
17 | "pako": "^2.1.0",
18 | "react": "^18.2.0",
19 | "react-big-calendar": "^1.13.1",
20 | "react-dom": "^18.2.0",
21 | "react-error-boundary": "^4.0.13",
22 | "react-hotkeys-hook": "^4.4.0",
23 | "react-scripts": "^5.0.1",
24 | "use-immer": "^0.9.0"
25 | },
26 | "homepage": "https://fede.dm/FIUBA-Plan",
27 | "scripts": {
28 | "start": "react-scripts start",
29 | "build": "react-scripts build",
30 | "eject": "react-scripts eject",
31 | "test": "jest"
32 | },
33 | "eslintConfig": {
34 | "extends": "react-app"
35 | },
36 | "browserslist": {
37 | "production": [
38 | ">0.2%",
39 | "not dead",
40 | "not op_mini all"
41 | ],
42 | "development": [
43 | "last 1 chrome version",
44 | "last 1 firefox version",
45 | "last 1 safari version"
46 | ]
47 | },
48 | "devDependencies": {
49 | "@babel/plugin-proposal-private-property-in-object": "7.21.11",
50 | "jest": "^27.5.1",
51 | "prettier": "3.2.4"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { ChakraProvider, Flex } from "@chakra-ui/react";
2 | import "@fontsource/source-sans-pro/400.css";
3 | import React from "react";
4 | import ReactDOM from "react-dom/client";
5 | import { ErrorBoundary } from "react-error-boundary";
6 | import Body from "./components/Body";
7 | import { DataProvider } from "./DataContext";
8 | import customTheme from "./theme";
9 |
10 | import { useToast } from '@chakra-ui/react'
11 |
12 | const App = () => {
13 | const toast = useToast();
14 |
15 | return (
16 | {
18 | console.warn(
19 | "Hubo un error inesperado. Se limpian los datos guardados",
20 | error
21 | );
22 |
23 | toast({
24 | title: "Ocurrió un error",
25 | description: "Se limpiaron los datos guardados.",
26 | status: "error",
27 | duration: 9000,
28 | isClosable: true,
29 | })
30 |
31 | // Llamamos resetErrorBoundary() para resetear el error boundary y volver
32 | // a intentar el render
33 | resetErrorBoundary();
34 | }}
35 | onReset={() => {
36 | localStorage.setItem("fiubaplan", JSON.stringify({}));
37 | }}
38 | >
39 |
40 |
41 |
42 |
43 |
44 |
45 | );
46 | };
47 |
48 | const container = document.getElementById("root");
49 | const root = ReactDOM.createRoot(container);
50 |
51 | root.render(
52 |
53 |
54 |
55 | );
56 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | import { Buffer } from "buffer";
2 | import ColorHash from "color-hash";
3 | import { useCombobox, useSelect } from "downshift";
4 | import pako from "pako";
5 |
6 | const arr = (min, max, int) => {
7 | const arr = [];
8 | for (let i = min; i <= max; i += int) {
9 | arr.push(i);
10 | }
11 | return arr;
12 | };
13 |
14 | const colorHash = new ColorHash({
15 | lightness: arr(0.6, 0.85, 0.1),
16 | saturation: arr(0.6, 0.85, 0.1),
17 | hash: "bkdr",
18 | });
19 |
20 | export const getColor = (event) => {
21 | if (!event) return null;
22 | return colorHash.hex(event.id.toString());
23 | };
24 |
25 | // Downshift util to not close the menu on an item selection (with click, space or enter)
26 | export function stateReducer(state, actionAndChanges) {
27 | const { changes, type } = actionAndChanges;
28 | switch (type) {
29 | case useCombobox.stateChangeTypes.InputKeyDownEnter:
30 | case useCombobox.stateChangeTypes.ItemClick:
31 | case useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
32 | case useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
33 | case useSelect.stateChangeTypes.ItemClick:
34 | return {
35 | ...changes,
36 | isOpen: true,
37 | highlightedIndex: state.highlightedIndex,
38 | };
39 | default:
40 | return changes;
41 | }
42 | }
43 |
44 | export function base64tojson(data) {
45 | // b64 => pako => json
46 | const savedataPako = Buffer.from(data, "base64");
47 | return JSON.parse(pako.ungzip(savedataPako, { to: "string" }));
48 | }
49 |
50 | export function jsontobase64(jsondata) {
51 | // json => pako => b64
52 | const savedataPako = pako.gzip(JSON.stringify(jsondata), { to: "string" });
53 | return Buffer.from(savedataPako).toString("base64");
54 | }
55 |
--------------------------------------------------------------------------------
/src/siuparser.js:
--------------------------------------------------------------------------------
1 | const SEMANA = [
2 | "Domingo",
3 | "Lunes",
4 | "Martes",
5 | "Miércoles",
6 | "Jueves",
7 | "Viernes",
8 | "Sábado",
9 | ];
10 |
11 | export function parseSIU(rawdata) {
12 | // Asegurarse:
13 | // - no agregar ningun curso sin clases
14 | // - no agregar ninguna materia sin cursos asociados
15 | // - no agregar periodos sin materias
16 |
17 | const result = [];
18 |
19 | const periodoPattern =
20 | /Período lectivo: ([^\n]+)\n[\s\S]*?(?=Período lectivo:|$)/g;
21 | const materiaPattern =
22 | /Actividad: ([^\n]+) \((.+?)\)\n[\s\S]*?(?=Actividad:|$)/g;
23 | const cursosPattern =
24 | /Comisión: ([^\n]+)[\s\S]*?Docentes: ([^\n]+)[\s\S]*?Tipo de clase\s+Día\s+Horario(?:\s+Aula)([\s\S]*?)(?=Comisión:|$)/g;
25 |
26 | const periodos = [];
27 | for (const periodoMatch of rawdata.matchAll(periodoPattern)) {
28 | const periodoFullText = periodoMatch[0];
29 | const periodoNombre = periodoMatch[1];
30 |
31 | console.debug(`Found periodo: ${periodoNombre}`)
32 | periodos.push({
33 | periodo: periodoNombre,
34 | raw: periodoFullText,
35 | materias: [],
36 | cursos: [],
37 | });
38 | }
39 |
40 | for (let periodo of periodos) {
41 | for (const materiaMatch of periodo.raw.matchAll(materiaPattern)) {
42 | const materiaFullText = materiaMatch[0];
43 | const materia = {
44 | nombre: materiaMatch[1],
45 | codigo: materiaMatch[2],
46 | cursos: [],
47 | };
48 | console.debug(`- Found materia: ${materia.nombre} (${materia.codigo})`)
49 |
50 | for (const cursoMatch of materiaFullText.matchAll(cursosPattern)) {
51 | const cursoCodigo = `${materia.codigo}-${cursoMatch[1]}`;
52 | const cursoDocentes = cursoMatch[2].trim().replace(/\(.*?\)/g, "");
53 | console.debug(`-- Found curso: ${cursoCodigo}`)
54 |
55 | const clases = [];
56 | for (let claseLine of cursoMatch[3].trim().split("\n")) {
57 | console.debug(`--- Found clase: ${claseLine}`)
58 | if (!SEMANA.some(day => claseLine.includes(day))) {
59 | continue;
60 | }
61 |
62 | // eslint-disable-next-line no-unused-vars
63 | const [_tipo, dia, horario, _aula = null] = claseLine.split("\t");
64 | const [inicio, fin] = horario.split(" a ");
65 | const clase = {
66 | dia: SEMANA.indexOf(dia),
67 | inicio,
68 | fin,
69 | };
70 | clases.push(clase);
71 | }
72 |
73 | if (clases.length === 0) {
74 | continue;
75 | }
76 |
77 | periodo.cursos.push({
78 | materia: materia.codigo,
79 | codigo: cursoCodigo,
80 | docentes: cursoDocentes,
81 | clases,
82 | });
83 | materia.cursos.push(cursoCodigo);
84 | }
85 |
86 | if (materia.cursos.length === 0) {
87 | continue;
88 | }
89 | periodo.materias.push(materia);
90 | }
91 |
92 | if (periodo.materias.length === 0) {
93 | continue;
94 | }
95 | result.push({
96 | periodo: periodo.periodo,
97 | materias: periodo.materias,
98 | cursos: periodo.cursos,
99 | timestamp: Date.now(),
100 | });
101 | }
102 | console.debug(result);
103 | return result;
104 | }
105 |
--------------------------------------------------------------------------------
/src/Style.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Source+Serif+Pro&display=swap");
2 |
3 | .rbc-calendar {
4 | background: var(--chakra-colors-calendarbg);
5 | }
6 |
7 | #dark .rbc-calendar {
8 | background: var(--chakra-colors-calendarbgdark);
9 | }
10 |
11 | .rbc-allday-cell {
12 | display: none;
13 | }
14 |
15 | .rbc-header,
16 | .rbc-label,
17 | .rbc-agenda-date-cell,
18 | .rbc-agenda-time-cell {
19 | font-family: "Source Serif Pro", serif;
20 | }
21 |
22 | .rbc-time-view {
23 | border: none;
24 | }
25 |
26 | .rbc-time-gutter {
27 | padding: 0 0.5em;
28 | font-weight: bold;
29 | font-size: large;
30 | color: var(--chakra-colors-drawerbg);
31 | margin-right: 5px;
32 | }
33 | #dark .rbc-time-gutter {
34 | color: var(--chakra-colors-primary-600);
35 | }
36 |
37 | .rbc-time-content > * + * > * {
38 | border: 3px solid;
39 | border-top: none;
40 | border-left: none;
41 | border-bottom: none;
42 | border-color: var(--chakra-colors-drawerbg);
43 | }
44 | #dark .rbc-time-content > * + * > * {
45 | border-color: var(--chakra-colors-primary-300);
46 | }
47 |
48 | .rbc-day-slot .rbc-event-label {
49 | width: 100%;
50 | text-align: left;
51 | }
52 |
53 | .rbc-day-slot .rbc-events-container {
54 | margin: 0;
55 | }
56 |
57 | .rbc-time-column:last-child * {
58 | border-right: none;
59 | }
60 |
61 | .rbc-timeslot-group {
62 | display: flex;
63 | flex-direction: row;
64 | align-items: center;
65 | border: none;
66 | }
67 | #dark .rbc-time-gutter .rbc-timeslot-group {
68 | border-bottom: 1px solid var(--chakra-colors-primary-300);
69 | }
70 | #dark .rbc-time-gutter .rbc-timeslot-group:last-child {
71 | border-bottom: none;
72 | }
73 |
74 | .rbc-row {
75 | height: 3em;
76 | line-height: 3em;
77 | }
78 |
79 | .rbc-header * {
80 | cursor: text;
81 | color: var(--chakra-colors-drawerbg);
82 | font-size: larger;
83 | }
84 | #dark .rbc-header * {
85 | color: var(--chakra-colors-primary-600);
86 | }
87 |
88 | .rbc-day-slot .rbc-timeslot-group:nth-child(even) {
89 | background: var(--chakra-colors-calendarbggrey);
90 | }
91 | #dark .rbc-day-slot .rbc-timeslot-group:nth-child(even) {
92 | background: var(--chakra-colors-agendabgdark);
93 | }
94 |
95 | .rbc-header {
96 | border: none;
97 | }
98 |
99 | .rbc-day-slot {
100 | border: none;
101 | }
102 |
103 | .rbc-day-slot .rbc-time-slot {
104 | border-top: none;
105 | }
106 |
107 | .rbc-time-content {
108 | border-top: none;
109 | }
110 |
111 | .rbc-header + .rbc-header {
112 | border-left: none;
113 | }
114 |
115 | .rbc-time-header-content {
116 | border: none;
117 | }
118 |
119 | .rbc-agenda-event-cell,
120 | .rbc-agenda-time-cell {
121 | font-size: small;
122 | line-height: 120%;
123 | }
124 |
125 | .rbc-agenda-time-cell {
126 | border: 1px solid var(--chakra-colors-primary-300);
127 | }
128 |
129 | .rbc-agenda-date-cell {
130 | background: var(--chakra-colors-calendarbggrey);
131 | border: none;
132 | }
133 |
134 | #dark .rbc-agenda-table .rbc-agenda-date-cell {
135 | background: var(--chakra-colors-calendarbgdark);
136 | }
137 |
138 | .rbc-agenda-event-cell-sub {
139 | font-size: x-small;
140 | color: var(--chakra-colors-drawerbg);
141 | }
142 |
143 | #dark .rbc-agenda-table * {
144 | background: var(--chakra-colors-agendabgdark);
145 | color: var(--chakra-colors-calendarbg);
146 | }
147 |
148 | #dark .rbc-agenda-table {
149 | border: none;
150 | }
151 |
--------------------------------------------------------------------------------
/src/components/Body.js:
--------------------------------------------------------------------------------
1 | import { AddIcon, Icon } from "@chakra-ui/icons";
2 | import {
3 | Box,
4 | IconButton,
5 | Tooltip,
6 | useColorModeValue,
7 | useDisclosure,
8 | } from "@chakra-ui/react";
9 | import "moment/locale/es";
10 | import React from "react";
11 | import "react-big-calendar/lib/css/react-big-calendar.css";
12 | import { useHotkeys } from "react-hotkeys-hook";
13 | import { DataContext } from "../DataContext";
14 | import useWindowSize from "../useWindowSize";
15 | import Calendar from "./Calendar";
16 | import ManualUploadModal from "./ManualUploadModal";
17 | import MateriasDrawer from "./MateriasDrawer";
18 |
19 | const Body = () => {
20 | const { events, horariosSIU, setSkipSIU, skipSIU } = React.useContext(DataContext);
21 | const [useAgenda, setUseAgenda] = React.useState(false);
22 | const { width } = useWindowSize();
23 | const {
24 | isOpen: isOpenDrawer,
25 | onToggle: onToggleDrawer,
26 | onClose: onCloseDrawer,
27 | } = useDisclosure();
28 | const {
29 | isOpen: isOpenModal,
30 | onToggle: onToggleModal,
31 | onClose: onCloseModal,
32 | } = useDisclosure();
33 |
34 | useHotkeys("esc", (horariosSIU || skipSIU) ? onToggleDrawer : onToggleModal, {
35 | enableOnFormTags: true,
36 | });
37 |
38 | React.useEffect(() => {
39 | setUseAgenda(width < 1000);
40 | }, [width]);
41 |
42 | return (
43 |
44 |
52 | setSkipSIU(true)}
56 | setSkipSIU={setSkipSIU}
57 | />
58 |
59 |
60 |
61 |
62 | {(!horariosSIU && !skipSIU) ? (
63 |
64 |
69 |
70 |
78 |
82 |
88 |
89 |
90 |
91 | }
92 | onClick={onToggleModal}
93 | colorScheme="primary"
94 | aria-label="Cargar horarios del SIU"
95 | />
96 |
97 | ) : (
98 |
99 | }
103 | onClick={onToggleDrawer}
104 | colorScheme="primary"
105 | aria-label="Agregar Materias"
106 | />
107 |
108 | )}
109 |
110 |
111 | );
112 | };
113 |
114 | export default Body;
115 |
--------------------------------------------------------------------------------
/src/components/Calendar.js:
--------------------------------------------------------------------------------
1 | import { Box, Text, CloseButton } from "@chakra-ui/react";
2 | import moment from "moment";
3 | import "moment/locale/es";
4 | import React from "react";
5 | import { Calendar, momentLocalizer } from "react-big-calendar";
6 | import "react-big-calendar/lib/css/react-big-calendar.css";
7 | import { DataContext } from "../DataContext";
8 | import useWindowSize from "../useWindowSize";
9 | import CalendarAgenda from "./CalendarAgenda";
10 | import CalendarWeek from "./CalendarWeek";
11 | import TabSystem from "./TabSystem";
12 | import { getColor } from "../utils";
13 |
14 | const localizer = momentLocalizer(moment);
15 | const min = new Date().setHours(7, 0, 0);
16 | const max = new Date().setHours(23, 30, 0);
17 |
18 | const MateriaEvent = (props) => {
19 | const { removeExtraFromTab } = React.useContext(DataContext);
20 | return (
21 | <>
22 | {!props.event.curso && (
23 | {
28 | ev.stopPropagation();
29 | removeExtraFromTab(props.event.id);
30 | }}
31 | />
32 | )}
33 |
34 |
35 |
36 | {props.event.title}
37 |
38 |
39 | {props.event.subtitle}
40 |
41 |
42 | >
43 | );
44 | };
45 |
46 | const MateriaEventAgenda = (props) => {
47 | return (
48 |
49 |
55 |
56 | {props.event.title}
57 |
58 |
59 |
60 | {props.event.subtitle}
61 |
62 |
63 | );
64 | };
65 |
66 | const MyCalendar = (props) => {
67 | const { events, useAgenda } = props;
68 | const { width } = useWindowSize();
69 | const { addExtra } = React.useContext(DataContext);
70 |
71 | const eventPropsGetter = React.useCallback(
72 | (event) => {
73 | let color = event.id ? getColor(event) : "inherit";
74 | const style = {
75 | borderWidth: "thin thin thin thick",
76 | borderRightColor: "#d2adf4", //primary.300
77 | borderBottomColor: "#d2adf4", //primary.300
78 | borderTopColor: "#d2adf4", //primary.300
79 | borderLeftColor: color,
80 | color: "#1f1f1f",
81 | cursor: "default",
82 | };
83 | const calendarWeekStyle = {
84 | textAlign: "right",
85 | backgroundColor: "#FFF",
86 | borderRightColor: "#0000",
87 | borderBottomColor: "#0000",
88 | borderTopColor: "#0000",
89 | boxShadow: "inset 0 0 0 1000px " + color + "44",
90 | };
91 | return {
92 | style: useAgenda ? style : { ...style, ...calendarWeekStyle },
93 | };
94 | },
95 | [useAgenda],
96 | );
97 |
98 | const coveredDays = events.map((e) => e.start.getDay());
99 | const notCoveredDays = [1, 2, 3, 4, 5].filter(
100 | (d) => !coveredDays.includes(d),
101 | );
102 | const dummyEvents = notCoveredDays.map((i) => ({
103 | start: new Date(2018, 0, i, 7),
104 | end: new Date(2018, 0, i, 23, 30),
105 | title: "",
106 | }));
107 |
108 | const formats = {
109 | dayFormat: (d) => {
110 | const f = d
111 | .toLocaleString("es-AR", {
112 | weekday: "long",
113 | })
114 | .toUpperCase();
115 | return width > 1180 ? f : f[0];
116 | },
117 | agendaDateFormat: (d) => {
118 | return d
119 | .toLocaleString("es-AR", {
120 | weekday: "long",
121 | })
122 | .toUpperCase();
123 | },
124 | timeGutterFormat: "HH:mm",
125 | };
126 |
127 | return (
128 | {}}
132 | view={useAgenda ? "calendarAgenda" : "calendarWeek"}
133 | views={{ calendarAgenda: CalendarAgenda, calendarWeek: CalendarWeek }}
134 | localizer={localizer}
135 | min={min}
136 | max={max}
137 | defaultDate={new Date(2018, 0, 1)} // Monday
138 | events={useAgenda ? [...events, ...dummyEvents] : events}
139 | eventPropGetter={eventPropsGetter}
140 | components={{
141 | event: useAgenda ? MateriaEventAgenda : MateriaEvent,
142 | toolbar: TabSystem,
143 | }}
144 | onSelectSlot={addExtra}
145 | dayLayoutAlgorithm="no-overlap"
146 | tooltipAccessor="tooltip"
147 | />
148 | );
149 | };
150 |
151 | export default MyCalendar;
152 |
--------------------------------------------------------------------------------
/src/components/CalendarAgenda.js:
--------------------------------------------------------------------------------
1 | import PropTypes from "prop-types";
2 | import React from "react";
3 | import * as dates from "react-big-calendar/lib/utils/dates";
4 | import { navigate } from "react-big-calendar/lib/utils/constants";
5 | import { inRange } from "react-big-calendar/lib/utils/eventLevels";
6 | import { isSelected } from "react-big-calendar/lib/utils/selection";
7 |
8 | function Agenda({
9 | selected,
10 | getters,
11 | accessors,
12 | localizer,
13 | components,
14 | length,
15 | date,
16 | events,
17 | onSelectEvent,
18 | }) {
19 | const contentRef = React.useRef(null);
20 | const tbodyRef = React.useRef(null);
21 |
22 | const renderDay = (day, events, dayKey) => {
23 | const { event: Event, date: AgendaDate } = components;
24 |
25 | events = events.filter((e) =>
26 | inRange(
27 | e,
28 | dates.startOf(day, "day"),
29 | dates.endOf(day, "day"),
30 | accessors,
31 | localizer,
32 | ),
33 | );
34 |
35 | return events.map((event, idx) => {
36 | let title = accessors.title(event);
37 | let end = accessors.end(event);
38 | let start = accessors.start(event);
39 |
40 | const userProps = getters.eventProp(
41 | event,
42 | start,
43 | end,
44 | isSelected(event, selected),
45 | );
46 |
47 | let dateLabel = idx === 0 && localizer.format(day, "agendaDateFormat");
48 | let first =
49 | idx === 0 ? (
50 |
51 | |
56 | {AgendaDate ? (
57 |
58 | ) : (
59 | dateLabel
60 | )}
61 | |
62 |
63 | ) : (
64 | false
65 | );
66 |
67 | return [
68 | first,
69 |
70 | |
71 | {timeRangeLabel(day, event)}
72 | |
73 | onSelectEvent && onSelectEvent(event, e)}
78 | >
79 | {Event ? : title}
80 | |
81 |
,
82 | ];
83 | }, []);
84 | };
85 |
86 | const timeRangeLabel = (day, event) => {
87 | let labelClass = "",
88 | TimeComponent = components.time,
89 | label = localizer.messages.allDay;
90 |
91 | let end = accessors.end(event);
92 | let start = accessors.start(event);
93 |
94 | if (!accessors.allDay(event)) {
95 | if (dates.eq(start, end)) {
96 | label = localizer.format(start, "agendaTimeFormat");
97 | } else if (dates.eq(start, end, "day")) {
98 | label = localizer.format({ start, end }, "agendaTimeRangeFormat");
99 | } else if (dates.eq(day, start, "day")) {
100 | label = localizer.format(start, "agendaTimeFormat");
101 | } else if (dates.eq(day, end, "day")) {
102 | label = localizer.format(end, "agendaTimeFormat");
103 | }
104 | }
105 |
106 | if (dates.gt(day, start, "day")) labelClass = "rbc-continues-prior";
107 | if (dates.lt(day, end, "day")) labelClass += " rbc-continues-after";
108 |
109 | return (
110 |
111 | {TimeComponent ? (
112 |
113 | ) : (
114 | label
115 | )}
116 |
117 | );
118 | };
119 |
120 | let { messages } = localizer;
121 | let end = dates.add(date, length, "day");
122 |
123 | let range = dates.range(date, end, "day");
124 |
125 | events = events.filter((event) =>
126 | inRange(event, date, end, accessors, localizer),
127 | );
128 |
129 | events.sort((a, b) => +accessors.start(a) - +accessors.start(b));
130 |
131 | return (
132 |
133 | {events.length !== 0 ? (
134 |
135 |
136 |
137 |
138 | {range.map((day, idx) => renderDay(day, events, idx))}
139 |
140 |
141 |
142 |
143 | ) : (
144 |
{messages.noEventsInRange}
145 | )}
146 |
147 | );
148 | }
149 |
150 | Agenda.propTypes = {
151 | events: PropTypes.array,
152 | date: PropTypes.instanceOf(Date),
153 | length: PropTypes.number.isRequired,
154 |
155 | selected: PropTypes.object,
156 |
157 | accessors: PropTypes.object.isRequired,
158 | components: PropTypes.object.isRequired,
159 | getters: PropTypes.object.isRequired,
160 | localizer: PropTypes.object.isRequired,
161 | };
162 |
163 | Agenda.defaultProps = {
164 | length: 30,
165 | };
166 |
167 | Agenda.range = (start, { length = Agenda.defaultProps.length }) => {
168 | let end = dates.add(start, length, "day");
169 | return { start, end };
170 | };
171 |
172 | Agenda.navigate = (date, action, { length = Agenda.defaultProps.length }) => {
173 | switch (action) {
174 | case navigate.PREVIOUS:
175 | return dates.add(date, -length, "day");
176 |
177 | case navigate.NEXT:
178 | return dates.add(date, length, "day");
179 |
180 | default:
181 | return date;
182 | }
183 | };
184 |
185 | Agenda.title = (start, { length = Agenda.defaultProps.length, localizer }) => {
186 | let end = dates.add(start, length, "day");
187 | return localizer.format({ start, end }, "agendaHeaderFormat");
188 | };
189 |
190 | export default Agenda;
191 |
--------------------------------------------------------------------------------
/src/components/ManualUploadModal.js:
--------------------------------------------------------------------------------
1 | import {
2 | Button,
3 | Code,
4 | Kbd,
5 | Link,
6 | ListItem,
7 | Modal,
8 | ModalBody,
9 | ModalCloseButton,
10 | ModalContent,
11 | ModalHeader,
12 | ModalOverlay,
13 | OrderedList,
14 | Select,
15 | Text,
16 | Textarea,
17 | useToast,
18 | Flex,
19 | } from "@chakra-ui/react";
20 | import React from "react";
21 | import { DataContext } from "../DataContext";
22 |
23 | const ManualUploadModal = ({ isOpen, onClose, onSkip, setSkipSIU }) => {
24 | const toast = useToast();
25 | const [error, setError] = React.useState("");
26 | const [siuData, setSiuData] = React.useState("");
27 | const [periodosOptions, setPeriodosOptions] = React.useState([]);
28 | const [selectedPeriod, setSelectedPeriod] = React.useState(null);
29 | const { applyHorariosSIU, getPeriodosSIU } = React.useContext(DataContext);
30 |
31 | const handleSuccessfulUpload = () => {
32 | setSkipSIU(false);
33 | onClose();
34 | toast({
35 | title: "Horarios del SIU aplicados",
36 | status: "success",
37 | duration: 2000,
38 | isClosable: true,
39 | });
40 | };
41 |
42 | return (
43 | {
48 | setError("");
49 | setSiuData("");
50 | setPeriodosOptions([]);
51 | setSelectedPeriod(null);
52 | }}
53 | >
54 |
55 |
56 | Importar horarios del SIU
57 |
58 |
59 |
60 | Lamentablemente, FIUBA ya no ofrece los horarios de
61 | las materias públicamente, por lo que cada usuario tiene que importar manualmente
62 | sus horarios desde el SIU.
63 |
64 |
65 |
66 | Para importar tu oferta horaria seguí estos pasos:
67 |
68 |
69 |
70 | Andá a{" "}
71 |
75 |
80 | Reportes > Oferta de comisiones
81 |
82 |
83 |
84 |
85 | Ahí seleccioná todo el contenido de la página (CTRL +{" "}
86 | A)
87 |
88 |
89 | Copia todo (CTRL + C)
90 |
91 |
92 | Pegalo en el siguiente cuadro de texto (CTRL +{" "}
93 | V).
94 |
95 |
96 |
182 |
183 |
184 | );
185 | };
186 |
187 | export default ManualUploadModal;
188 |
--------------------------------------------------------------------------------
/src/components/Sugerencias.js:
--------------------------------------------------------------------------------
1 | import { ChatIcon, ExternalLinkIcon } from "@chakra-ui/icons";
2 | import {
3 | Alert,
4 | AlertDescription,
5 | AlertTitle,
6 | Box,
7 | CloseButton,
8 | DarkMode,
9 | Flex,
10 | IconButton,
11 | Link,
12 | Tag,
13 | TagLabel,
14 | TagRightIcon,
15 | Text,
16 | Textarea,
17 | useToast,
18 | } from "@chakra-ui/react";
19 | import React from "react";
20 |
21 | const submitBug = async (bug) => {
22 | if (!bug) return;
23 | const formData = new FormData();
24 | formData.append(`entry.108884877`, "FIUBA-PLAN");
25 | formData.append(`entry.817568535`, bug || "");
26 | fetch(
27 | `https://docs.google.com/forms/d/1Mr4-4qWqZKaobjG3GI30aPvC5qlMsd6Eib3YGUbLd2k/formResponse`,
28 | {
29 | body: formData,
30 | method: "POST",
31 | },
32 | );
33 | };
34 |
35 | // Toast para reportar bugs
36 | const Sugerencias = ({ onClose }) => {
37 | const bugToast = React.useRef();
38 | const toast = useToast();
39 |
40 | return (
41 |
42 | {
48 | onClose();
49 | if (toast.isActive(bugToast.current)) {
50 | toast.close(bugToast.current);
51 | return;
52 | }
53 |
54 | return (bugToast.current = toast({
55 | status: "info",
56 | position: "bottom",
57 | duration: null,
58 | isClosable: true,
59 | render: (props) => (
60 |
76 |
77 | Hola!
78 |
79 |
80 | Si encontrás algo feo, incorrecto, lento, erroneo... me
81 | decís?
82 |
83 |
84 | Si ves algo que te gustó, o tenés alguna idea, también!
85 |
86 |
87 | Si el parseo del SIU no esta funcionando como esperabas,
88 | describime el problema y pega el copypaste que usaste acá
89 | tambien.
90 |
91 |
92 | Estas sugerencias son *anónimas*. Si querés que te
93 | responda, escribime tu mail o telegram!
94 |
95 |
131 |
132 | ¿Usás Github? Me ayudás mucho más levantando un issue{" "}
133 |
145 | directamente{" "}
146 |
155 |
156 |
157 |
158 |
159 | toast.close(props.id)}
167 | position="absolute"
168 | right="8px"
169 | top="8px"
170 | />
171 |
172 | ),
173 | }));
174 | }}
175 | >
176 | Sugerencias
177 |
178 |
179 |
180 | );
181 | };
182 |
183 | export default Sugerencias;
184 |
--------------------------------------------------------------------------------
/tests/siuparser.test.js:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import fs from "node:fs";
3 | import { parseSIU } from "../src/siuparser";
4 |
5 | const directoryPath = path.dirname(__filename);
6 | const siusNames = fs
7 | .readdirSync(path.join(directoryPath, "siu-json"))
8 | .map((f) => path.parse(f).name);
9 |
10 | const sius = siusNames.map((siuName) => {
11 | const siuRawDataPath = path.join(directoryPath, "siu-raw", `${siuName}.js`);
12 | const siuJSONPath = path.join(directoryPath, "siu-json", `${siuName}.json`);
13 |
14 | const siuRawData = fs.readFileSync(siuRawDataPath, "utf8");
15 | const siuJSONData = JSON.parse(fs.readFileSync(siuJSONPath, "utf8"));
16 |
17 | return [siuName, siuRawData, siuJSONData];
18 | });
19 |
20 | describe.each(sius)("siu parser tests", (siuName, siuRawData, siuJSON) => {
21 | console.debug = jest.fn(); // Deshabilitar el debugging que se usa en el browser
22 | const parsedSIU = parseSIU(siuRawData);
23 |
24 | // Testear que los sius parseados no hayan cambiado en comparacion
25 | // con una copia anterior en JSON
26 | test(`${siuName} parsed siu does not change`, () => {
27 | siuJSON.forEach((json, index) => {
28 | json.timestamp = parsedSIU[index].timestamp;
29 | });
30 |
31 | expect(parsedSIU).toEqual(siuJSON);
32 | });
33 |
34 | // Recursivamente testear que no haya ninguna string o array vacios
35 | test(`${siuName} parsed siu has not empty strings nor arrays`, () => {
36 | const recursiveTest = (obj) => {
37 | for (const prop in obj) {
38 | if (!obj.hasOwnProperty(prop)) continue;
39 | if (typeof obj[prop] === "string")
40 | expect(obj[prop].length).toBeGreaterThan(0);
41 | else {
42 | if (Array.isArray(obj[prop]))
43 | expect(obj[prop].length).toBeGreaterThan(0);
44 | if (typeof obj[prop] === "object" && typeof obj[prop] !== null)
45 | recursiveTest(obj[prop]);
46 | }
47 | }
48 | };
49 |
50 | recursiveTest(parsedSIU);
51 | });
52 |
53 | // Testear que el nombre de cada periodo no sea una string vacia
54 | test(`${siuName} periodo is a non-empty string`, () => {
55 | parsedSIU.forEach((periodo) => {
56 | expect(typeof periodo.periodo).toBe("string");
57 | expect(periodo.periodo.length).toBeGreaterThan(0);
58 | });
59 | });
60 |
61 | // Testear que cada periodo no tenga ni materias ni cursos vacios
62 | test(`${siuName} periodos materias and cursos is not empty`, () => {
63 | parsedSIU.forEach((periodo) => {
64 | expect(periodo.materias.length).toBeGreaterThan(0);
65 | expect(periodo.cursos.length).toBeGreaterThan(0);
66 | });
67 | });
68 |
69 | // Testear que no hayan materias ni cursos con codigos repetidos
70 | test.each([["materias"], ["cursos"]])(
71 | `${siuName} periodos has not repeated %s codigos`,
72 | (prop) => {
73 | parsedSIU.forEach((periodo) => {
74 | const codigosArray = periodo[prop].map((m) => {
75 | return m.codigo;
76 | });
77 | const hasRepeatedCodigos = codigosArray.some((codigo, index, array) => {
78 | return array.indexOf(codigo) !== index;
79 | });
80 | expect(hasRepeatedCodigos).toBeFalsy();
81 | });
82 | },
83 | );
84 |
85 | // Testear que no hayan materias con el nombre o codigo vacios
86 | test.each([["codigo"], ["nombre"]])(
87 | `${siuName} every materia has a %s`,
88 | (prop) => {
89 | parsedSIU.forEach((periodo) => {
90 | periodo.materias.forEach((materia) => {
91 | expect(typeof materia[prop]).toBe("string");
92 | expect(materia[prop].length).toBeGreaterThan(0);
93 | });
94 | });
95 | },
96 | );
97 |
98 | // Testear en cada periodo, que los cursos de cada materia existan en
99 | // los cursos globales
100 | test(`${siuName} every materia cursos exists in global cursos`, () => {
101 | const globalCodigos = parsedSIU
102 | .map((periodo) => {
103 | return periodo.cursos.map((curso) => curso.codigo);
104 | })
105 | .flat(Infinity);
106 |
107 | parsedSIU.forEach((periodo) => {
108 | periodo.materias.forEach((materia) => {
109 | materia.cursos.forEach((codigoCurso) => {
110 | expect(globalCodigos.includes(codigoCurso)).toBeTruthy();
111 | });
112 | });
113 | });
114 | });
115 |
116 | // Testear en cada periodo, que cada curso global sea el curso de
117 | // alguna materia
118 | test(`${siuName} every global curso exists in a materia cursos`, () => {
119 | const cursosCodigos = parsedSIU
120 | .map((periodo) => {
121 | return periodo.materias.map((materia) => materia.cursos);
122 | })
123 | .flat(Infinity);
124 |
125 | parsedSIU.forEach((periodo) => {
126 | periodo.cursos.forEach((curso) => {
127 | expect(cursosCodigos.includes(curso.materia));
128 | });
129 | });
130 | });
131 |
132 | // Testear que cada materia tiene cursos
133 | test(`${siuName} every materia has cursos`, () => {
134 | parsedSIU.forEach((periodo) => {
135 | periodo.materias.forEach((materia) => {
136 | expect(materia.cursos.length).not.toBe(0);
137 |
138 | materia.cursos.forEach((curso) => {
139 | expect(typeof curso).toBe("string");
140 | expect(curso.length).toBeGreaterThan(0);
141 | });
142 | });
143 | });
144 | });
145 |
146 | // Testear que el dia de cada clase este en el intervalo del 1 al 6
147 | // (lunes a sabado)
148 | test(`${siuName} every class allows expected weekdays`, () => {
149 | parsedSIU.forEach((periodo) => {
150 | periodo.cursos.forEach((curso) => {
151 | curso.clases.forEach((clase) => {
152 | expect(clase.dia).toBeGreaterThanOrEqual(1);
153 | expect(clase.dia).toBeLessThanOrEqual(6);
154 | });
155 | });
156 | });
157 | });
158 |
159 | // Testear que el horario de cada clase cumpla con el formato "hora:hora"
160 | test(`${siuName} every class allows expected horarios`, () => {
161 | parsedSIU.forEach((periodo) => {
162 | periodo.cursos.forEach((curso) => {
163 | curso.clases.forEach((clase) => {
164 | ["inicio", "fin"].forEach((prop) => {
165 | expect(typeof clase[prop]).toBe("string");
166 | expect(clase[prop]).toMatch(/[0-9]{1,2}:[0-9]{1,2}/);
167 | });
168 | });
169 | });
170 | });
171 | });
172 |
173 | // Testear que el timestamp de cada periodo es mayor al 14/11/2023
174 | test(`${siuName} timestamp matches expected`, () => {
175 | parsedSIU.forEach((periodo) => {
176 | expect(Number.isInteger(periodo.timestamp)).toBeTruthy();
177 | expect(periodo.timestamp).toBeGreaterThan(1700000000);
178 | });
179 | });
180 | });
181 |
--------------------------------------------------------------------------------
/src/components/SelectExtra.js:
--------------------------------------------------------------------------------
1 | import {
2 | CheckIcon,
3 | ChevronDownIcon,
4 | ChevronUpIcon,
5 | EditIcon,
6 | MinusIcon,
7 | SmallCloseIcon,
8 | } from "@chakra-ui/icons";
9 | import {
10 | Box,
11 | Button,
12 | Editable,
13 | EditableInput,
14 | EditablePreview,
15 | Flex,
16 | IconButton,
17 | List,
18 | Text,
19 | Tooltip,
20 | useEditableControls,
21 | } from "@chakra-ui/react";
22 | import { useSelect } from "downshift";
23 | import React from "react";
24 | import { useHotkeys } from "react-hotkeys-hook";
25 | import { DataContext } from "../DataContext";
26 | import { getColor, stateReducer } from "../utils";
27 |
28 | const SelectExtra = () => {
29 | const {
30 | events,
31 | extraEvents,
32 | renameExtra,
33 | toggleExtra,
34 | removeExtra,
35 | removeAllExtra,
36 | } = React.useContext(DataContext);
37 |
38 | const {
39 | isOpen,
40 | getItemProps,
41 | getToggleButtonProps,
42 | getMenuProps,
43 | highlightedIndex,
44 | } = useSelect({
45 | stateReducer,
46 | items: extraEvents,
47 | });
48 |
49 | useHotkeys("space, enter", () => {
50 | if (highlightedIndex === -1) return;
51 | const event = extraEvents[highlightedIndex];
52 | toggleExtra(event.id);
53 | });
54 |
55 | return (
56 | <>
57 |
58 | {
61 | event.preventDownshiftDefault = true;
62 | },
63 | })}
64 | >
65 | : }
73 | >
74 | EXTRACURRICULAR
75 |
76 |
77 |
78 |
79 | }
87 | onClick={() => {
88 | removeAllExtra();
89 | }}
90 | />
91 |
92 |
93 |
94 |
106 | {extraEvents.map((item, index) => {
107 | const event = events.find((i) => i.id === item.id);
108 | const isActive = !!event;
109 | const color = getColor(event);
110 |
111 | return (
112 | {
120 | toggleExtra(item.id);
121 | }}
122 | _notLast={{
123 | borderBottom: "1px dashed violet",
124 | }}
125 | key={[item.id, isActive].join("-")}
126 | >
127 |
133 | {
139 | renameExtra(item.id, str);
140 | }}
141 | >
142 |
143 |
144 | {isActive && }
145 |
146 | {
150 | e.stopPropagation();
151 | }}
152 | _focus={{
153 | boxShadow: "0 0 0 1px rgba(183,148,244, 0.6)",
154 | }}
155 | />
156 |
157 |
158 |
159 |
160 | {
169 | removeExtra(item.id);
170 | e.stopPropagation();
171 | }}
172 | icon={}
173 | />
174 |
175 |
176 |
177 |
178 |
179 |
180 | );
181 | })}
182 |
183 | >
184 | );
185 | };
186 |
187 | function EditableControls({ color }) {
188 | const { isEditing, getSubmitButtonProps, getEditButtonProps } =
189 | useEditableControls();
190 |
191 | return isEditing ? (
192 | }
201 | {...getSubmitButtonProps()}
202 | onClick={(e) => {
203 | getSubmitButtonProps().onClick(e);
204 | e.stopPropagation();
205 | }}
206 | />
207 | ) : (
208 |
209 | }
218 | {...getEditButtonProps()}
219 | onClick={(e) => {
220 | getEditButtonProps().onClick(e);
221 | e.stopPropagation();
222 | }}
223 | />
224 |
225 | );
226 | }
227 |
228 | export default SelectExtra;
229 |
--------------------------------------------------------------------------------
/src/components/SelectMateria.js:
--------------------------------------------------------------------------------
1 | import { CheckIcon, ChevronRightIcon } from "@chakra-ui/icons";
2 | import {
3 | Box,
4 | Button,
5 | Menu,
6 | MenuButton,
7 | MenuOptionGroup,
8 | MenuItemOption,
9 | MenuList,
10 | Icon,
11 | Input,
12 | InputGroup,
13 | InputRightElement,
14 | List,
15 | Tooltip,
16 | Portal,
17 | } from "@chakra-ui/react";
18 | import { useCombobox } from "downshift";
19 | import React from "react";
20 | import { useHotkeys } from "react-hotkeys-hook";
21 | import { DataContext } from "../DataContext";
22 | import { stateReducer } from "../utils";
23 |
24 | const SEMANA = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"];
25 |
26 | const SelectMateria = ({ materiasToShow, drawerRef }) => {
27 | const { getters, toggleMateria, selectedMaterias } =
28 | React.useContext(DataContext);
29 | const [search, setSearch] = React.useState("");
30 | const [selectedDays, setSelectedDays] = React.useState([1, 2, 3, 4, 5, 6]);
31 |
32 | const filterDays = React.useCallback(
33 | (materia) => {
34 | for (const curso of getters.getCursosMateria(materia.codigo)) {
35 | for (const clase of curso.clases) {
36 | if (selectedDays.includes(clase.dia)) {
37 | return true;
38 | }
39 | }
40 | }
41 |
42 | return false;
43 | },
44 | [getters, selectedDays],
45 | );
46 |
47 | const inputItems = React.useMemo(() => {
48 | return materiasToShow.filter(filterDays).filter(
49 | (item) =>
50 | item.nombre
51 | .toLowerCase()
52 | .normalize("NFD")
53 | .replace(/[\u0300-\u036f]/g, "")
54 | .includes(search) || item.codigo.includes(search),
55 | );
56 | }, [filterDays, materiasToShow, search]);
57 |
58 | const {
59 | isOpen,
60 | getToggleButtonProps,
61 | getMenuProps,
62 | getInputProps,
63 | getItemProps,
64 | highlightedIndex,
65 | } = useCombobox({
66 | items: inputItems,
67 | itemToString: (item) => search,
68 | onInputValueChange: ({ inputValue }) => {
69 | setSearch(
70 | inputValue
71 | .toLowerCase()
72 | .normalize("NFD")
73 | .replace(/[\u0300-\u036f]/g, ""),
74 | );
75 | },
76 | stateReducer,
77 | });
78 |
79 | useHotkeys(
80 | "enter",
81 | () => {
82 | if (highlightedIndex === -1) return;
83 | const materia = inputItems[highlightedIndex];
84 | toggleMateria(materia.codigo);
85 | },
86 | { enableOnFormTags: ["input"] },
87 | );
88 |
89 | return (
90 | <>
91 |
92 |
103 |
106 |
113 |
114 |
127 |
128 |
129 | }
130 | />
131 |
132 |
133 |
138 | {SEMANA.map((day, index) => {
139 | return (
140 |
141 | {day}
142 |
143 | );
144 | })}
145 |
146 |
147 |
148 |
149 | }
150 | />
151 |
152 |
153 |
167 | {inputItems.length ? (
168 | inputItems
169 | .sort((a, b) => a.codigo > b.codigo)
170 | .map((materia, index) => (
171 | toggleMateria(materia.codigo)}
182 | key={materia.codigo}
183 | >
184 |
190 | {selectedMaterias.includes(materia.codigo) ? (
191 |
192 | ) : (
193 |
194 | )}
195 | ({materia.codigo}) {materia.nombre}
196 |
197 |
198 | ))
199 | ) : (
200 |
201 | No se encontraron materias.
202 |
203 | )}
204 |
205 | >
206 | );
207 | };
208 |
209 | export default SelectMateria;
210 |
--------------------------------------------------------------------------------
/src/components/SelectCurso.js:
--------------------------------------------------------------------------------
1 | import {
2 | CheckIcon,
3 | ChevronDownIcon,
4 | ChevronUpIcon,
5 | MinusIcon,
6 | WarningTwoIcon,
7 | } from "@chakra-ui/icons";
8 | import {
9 | Badge,
10 | Box,
11 | Button,
12 | Flex,
13 | IconButton,
14 | List,
15 | Text,
16 | Tooltip,
17 | } from "@chakra-ui/react";
18 | import { useSelect } from "downshift";
19 | import React from "react";
20 | import { useHotkeys } from "react-hotkeys-hook";
21 | import { DataContext } from "../DataContext";
22 | import { getColor, stateReducer } from "../utils";
23 |
24 | const INICIALES_SEMANA = ["D", "L", "M", "X", "J", "V", "S"];
25 |
26 | const SelectCurso = ({ codigo }) => {
27 | const { toggleCurso, events, toggleMateria, getters } =
28 | React.useContext(DataContext);
29 | const materia = getters.getMateria(codigo);
30 | const items = getters.getCursosMateria(codigo);
31 |
32 | const isBlocked = React.useCallback(
33 | (codigo) => {
34 | const curso = getters.getCurso(codigo);
35 | const eventos = events.filter((e) => {
36 | const anotherCurso = getters.getCurso(e.curso);
37 | if (!anotherCurso) return false;
38 | return anotherCurso.materia !== curso.materia;
39 | });
40 | for (const clase of curso.clases) {
41 | const inicio = new Date(2018, 0, clase.dia);
42 | const [inicioHora, inicioMinutos] = clase.inicio.split(":");
43 | inicio.setHours(inicioHora, inicioMinutos);
44 | const fin = new Date(2018, 0, clase.dia);
45 | const [finHora, finMinutos] = clase.fin.split(":");
46 | fin.setHours(finHora, finMinutos);
47 |
48 | for (const evento of eventos) {
49 | if (inicio < evento.end && fin > evento.start) {
50 | return true;
51 | }
52 | }
53 | }
54 | return false;
55 | },
56 | [events, getters],
57 | );
58 |
59 | const allItemsBlocked = items.every((item) => isBlocked(item.codigo));
60 |
61 | const {
62 | isOpen,
63 | getItemProps,
64 | getToggleButtonProps,
65 | highlightedIndex,
66 | getMenuProps,
67 | } = useSelect({
68 | stateReducer,
69 | items,
70 | });
71 |
72 | useHotkeys("space, enter", () => {
73 | if (highlightedIndex === -1) return;
74 | const curso = items[highlightedIndex];
75 | toggleCurso(curso.codigo);
76 | });
77 |
78 | return (
79 | <>
80 |
81 | {allItemsBlocked && (
82 |
87 | Todos los cursos de esta materia
88 | se solapan con otros cursos
89 | >
90 | }
91 | >
92 |
93 |
94 | )}
95 |
96 |
127 |
128 |
129 |
130 | }
138 | onClick={() => {
139 | toggleMateria(materia.codigo);
140 | }}
141 | />
142 |
143 |
144 |
145 |
157 | {items.map((item, index) => {
158 | const event = events.find((i) => i.curso === item.codigo);
159 | const isActive = !!event;
160 | const color = getColor(event);
161 | const isItemBlocked = isBlocked(item.codigo);
162 | return (
163 |
170 | Este curso se solapa
171 | con otros cursos
172 | >
173 | ) : undefined
174 | }
175 | key={item.codigo}
176 | >
177 | toggleCurso(item.codigo)}
185 | _notLast={{
186 | borderBottom: "1px dashed violet",
187 | }}
188 | key={item.codigo}
189 | position="relative"
190 | >
191 |
197 | {isActive && }
198 | {isItemBlocked && }
199 | {item.docentes}
200 |
206 | {[
207 | ...new Set(
208 | item.clases.map((clase) => INICIALES_SEMANA[clase.dia]),
209 | ),
210 | ].join(" | ")}
211 |
212 |
213 |
214 |
215 | );
216 | })}
217 |
218 | >
219 | );
220 | };
221 |
222 | export default SelectCurso;
223 |
--------------------------------------------------------------------------------
/src/components/TabSystem.js:
--------------------------------------------------------------------------------
1 | import { AddIcon, SmallCloseIcon } from "@chakra-ui/icons";
2 | import {
3 | Alert,
4 | AlertDescription,
5 | AlertIcon,
6 | AlertTitle,
7 | Box,
8 | Button,
9 | CloseButton,
10 | Editable,
11 | EditableInput,
12 | EditablePreview,
13 | Flex,
14 | IconButton,
15 | LightMode,
16 | Popover,
17 | PopoverArrow,
18 | PopoverBody,
19 | PopoverContent,
20 | PopoverFooter,
21 | PopoverTrigger,
22 | Tab,
23 | Tabs,
24 | Text,
25 | useTab,
26 | useToast
27 | } from "@chakra-ui/react";
28 | import "moment/locale/es";
29 | import React from "react";
30 | import { DataContext } from "../DataContext";
31 |
32 | const TabSystem = (props) => {
33 | const {
34 | activeTabId,
35 | tabs,
36 | selectTab,
37 | addTab,
38 | readOnly,
39 | setReadOnly,
40 | horariosSIU,
41 | errorPermalink,
42 | setErrorPermalink,
43 | } = React.useContext(DataContext);
44 | const toastPermalink = useToast();
45 | const toastError = useToast();
46 | const inputref = React.useRef(null);
47 | const [readOnlyToastClosed, setReadOnlyToastClosed] = React.useState(false);
48 |
49 | if (readOnly && !toastPermalink.isActive("readonly") && !readOnlyToastClosed) {
50 | toastPermalink({
51 | id: "readonly",
52 | duration: null,
53 | isClosable: false,
54 | position: "bottom-start",
55 | onCloseComplete: () => {
56 | setReadOnlyToastClosed(true);
57 | },
58 | render: () => (
59 |
60 |
68 | {
72 | toastPermalink.closeAll();
73 | }}
74 | position="absolute"
75 | insetEnd={1}
76 | top={1}
77 | />
78 |
79 | Estás navegando desde un permalink
80 |
81 | Para volver a tu plan anterior, recarga la página.
82 |
83 | Para utilizar este plan como tuyo, guardalo.
84 |
85 |
86 |
99 |
100 |
101 | ),
102 | });
103 | }
104 |
105 | if (errorPermalink && !toastError.isActive("errorToast")) {
106 | toastError({
107 | id: "errorToast",
108 | position: "bottom-start",
109 | duration: 5000,
110 | onCloseComplete: () => {
111 | setErrorPermalink(false);
112 | },
113 | render: () => (
114 |
115 |
116 |
117 | El plan no se pudo cargar correctamente
118 | Si estás desde un celular, probalo en la compu!
119 |
120 | toastError.closeAll("errorToast")} />
121 |
122 | ),
123 | });
124 | }
125 |
126 | return (
127 |
132 | {
134 | if (e.keyCode === 32) {
135 | e.preventDefault();
136 | const ch = e.target.selectionStart;
137 | inputref.current.value =
138 | e.target.value.slice(0, ch) + " " + e.target.value.slice(ch);
139 | e.target.selectionStart = ch + 1;
140 | e.target.selectionEnd = ch + 1;
141 | }
142 | }}
143 | index={tabs.map((t) => t.id).indexOf(activeTabId)}
144 | key={tabs.length}
145 | colorScheme="purple"
146 | onChange={(index) => {
147 | selectTab(tabs[index]?.id || 0);
148 | }}
149 | >
150 |
151 | {tabs.map((tab, index) => (
152 |
158 | ))}
159 |
160 | {tabs.length < 5 && (
161 | {
166 | addTab();
167 | }}
168 | icon={}
169 | />
170 | )}
171 |
172 |
173 | {horariosSIU && (
174 |
175 |
176 |
177 |
178 | Usando horarios del SIU
179 |
180 | {horariosSIU.periodo}
181 |
182 |
183 |
184 |
185 |
186 | Acordate que el SIU también puede actualizar sus horarios sin
187 | aviso previo. Si estás por inscribirte a materias, es
188 | recomendable que re-cargues los horarios.
189 |
190 |
191 | Horarios cargados el{" "}
192 |
193 | {new Date(horariosSIU.timestamp).toLocaleString()}
194 |
195 |
196 |
197 |
198 |
199 | )}
200 |
201 | );
202 | };
203 |
204 | const CustomTab = React.forwardRef((props, ref) => {
205 | const { renameTab, removeTab } = React.useContext(DataContext);
206 | const tabProps = useTab({ ...props, ref });
207 | const isSelected = !!tabProps["aria-selected"];
208 |
209 | return (
210 |
211 | {
217 | ev.stopPropagation();
218 | }}
219 | onSubmit={(str) => {
220 | renameTab(props.tab.id, str);
221 | }}
222 | >
223 |
224 |
225 |
232 | {props.tab.id !== 0 && isSelected && (
233 | {
239 | removeTab(props.tab.id);
240 | }}
241 | />
242 | )}
243 |
244 |
245 |
246 | );
247 | });
248 |
249 | export default TabSystem;
250 |
--------------------------------------------------------------------------------
/src/components/MateriasDrawer.js:
--------------------------------------------------------------------------------
1 | import {
2 | CalendarIcon,
3 | DeleteIcon,
4 | LinkIcon,
5 | MoonIcon,
6 | SunIcon,
7 | } from "@chakra-ui/icons";
8 | import {
9 | Alert,
10 | AlertIcon,
11 | AlertTitle,
12 | Box,
13 | Button,
14 | Drawer,
15 | DrawerBody,
16 | DrawerContent,
17 | DrawerFooter,
18 | DrawerOverlay,
19 | Flex,
20 | Icon,
21 | IconButton,
22 | LightMode,
23 | Link,
24 | Tooltip,
25 | useClipboard,
26 | useColorMode,
27 | useColorModeValue,
28 | useToast,
29 | } from "@chakra-ui/react";
30 | import React from "react";
31 | import { DataContext } from "../DataContext";
32 | import SelectCurso from "./SelectCurso";
33 | import SelectExtra from "./SelectExtra";
34 | import SelectMateria from "./SelectMateria";
35 | import Sugerencias from "./Sugerencias";
36 |
37 | const MateriasDrawer = (props) => {
38 | const { useAgenda, setUseAgenda, isOpen, onClose, skipSIU, onOpenModal } = props;
39 | const {
40 | tabs,
41 | selectedMaterias,
42 | limpiarTab,
43 | activeTabId,
44 | events,
45 | extraEvents,
46 | permalink,
47 | horariosSIU,
48 | getters,
49 | removeHorariosSIU,
50 | } = React.useContext(DataContext);
51 | const permalinkToast = React.useRef();
52 | const drawerRef = React.useRef();
53 | const { toggleColorMode } = useColorMode();
54 | const toast = useToast();
55 | const { onCopy } = useClipboard(permalink);
56 |
57 | const materiasToShow = React.useMemo(() => {
58 | if (!horariosSIU) return [];
59 |
60 | const codigos = horariosSIU.materias.map((m) => m.codigo);
61 | const codigosUnicos = [...new Set(codigos)].sort();
62 | const materias = codigosUnicos.map(getters.getMateria);
63 |
64 | return materias;
65 | }, [getters.getMateria, horariosSIU]);
66 |
67 | return (
68 |
69 |
70 |
71 |
74 |
75 | {skipSIU ? (
76 |
86 | ) : (
87 | horariosSIU && (
88 | }
91 | colorScheme="red"
92 | onClick={async () => {
93 | await removeHorariosSIU();
94 | onClose();
95 | }}
96 | >
97 | Dejar de usar horarios del SIU
98 |
99 | )
100 | )}
101 |
102 |
103 | {horariosSIU && (
104 |
105 |
109 |
110 | )}
111 |
112 |
119 | {selectedMaterias.map((m) => (
120 |
121 | ))}
122 | {!!extraEvents.length && }
123 |
124 |
125 |
126 | {!!events.length && (
127 |
147 | )}
148 |
149 |
150 |
151 |
152 |
153 | }
158 | onClick={() => setUseAgenda(!useAgenda)}
159 | />
160 |
161 |
162 |
163 | }
168 | onClick={() => {
169 | onClose();
170 | onCopy();
171 | toast.close(permalinkToast.current);
172 | return (permalinkToast.current = toast({
173 | position: "bottom-start",
174 | duration: 1500,
175 | render: () => (
176 |
177 |
184 |
185 | Permalink copiado!
186 |
187 |
188 | ),
189 | }));
190 | }}
191 | />
192 |
193 |
194 |
195 |
196 |
200 |
201 | {useColorModeValue(, )}
202 |
203 |
204 |
205 |
206 |
211 |
212 |
216 |
217 |
218 |
219 |
220 |
221 |
226 |
227 |
231 |
232 |
233 |
234 |
235 |
236 |
241 |
242 |
246 |
247 |
248 |
249 |
250 |
251 |
256 |
257 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 | );
272 | };
273 |
274 | export default MateriasDrawer;
275 |
--------------------------------------------------------------------------------
/src/DataContext.js:
--------------------------------------------------------------------------------
1 | /* https://github.com/facebook/react/issues/14476#issuecomment-471199055 */
2 | /* eslint-disable react-hooks/exhaustive-deps */
3 |
4 | import React from "react";
5 | import { useImmer, useImmerReducer } from "use-immer";
6 | import { parseSIU } from "./siuparser";
7 | import { base64tojson, jsontobase64 } from "./utils";
8 |
9 | // Si tengo un permalink, parseo su info y reseteo la URL
10 | let permalinksavedata = null;
11 | if (window.location.hash) {
12 | try {
13 | permalinksavedata = base64tojson(window.location.hash.slice(1));
14 | } catch (error) {
15 | permalinksavedata = "";
16 | }
17 | // eslint-disable-next-line no-restricted-globals
18 | history.pushState("", "", window.location.pathname + window.location.search);
19 | }
20 |
21 | // Si el usuario tiene una sesión de cuando la aplicación tenía horarios estaticos
22 | // en vez de importados del SIU (la key `cuatrimestre`), le limpiamos la data
23 | let json = null;
24 | try {
25 | json = JSON.parse(window.localStorage.getItem("fiubaplan"));
26 | } catch (e) {
27 | console.warn("Error al parsear el JSON del localStorage", e);
28 | } finally {
29 | if (!json || json["cuatrimestre"]) {
30 | window.localStorage.setItem("fiubaplan", JSON.stringify({}));
31 | }
32 | }
33 |
34 | export const DataContext = React.createContext();
35 |
36 | export const DataProvider = ({ children }) => {
37 | const data = Data();
38 |
39 | return {children};
40 | };
41 |
42 | const Data = () => {
43 | // Utilizamos errorPermalink para handlear si hubo un error procesando
44 | // el permalink, y si lo hubo redireccionar a la home y mostrar un toast (en TabSystem.js)
45 | // informando al usuario que hubo un error
46 | const [errorPermalink, setErrorPermalink] = React.useState(permalinksavedata === "");
47 | // ESTADO 0: el usuario cargo a manopla los horarios de su propio SIU, o decide no usarlos
48 | const [horariosSIU, setHorariosSIU] = React.useState(initialHorariosSIU);
49 | const [skipSIU, setSkipSIU] = React.useState(getFromStorage("skipSIU") || false);
50 |
51 | // Getters que verifican contra el SIU del usuario
52 | const getters = React.useMemo(() => {
53 | const getMateria = (codigo) => {
54 | return horariosSIU?.materias.find((m) => m.codigo === codigo);
55 | };
56 |
57 | const getCurso = (codigo) => {
58 | return horariosSIU?.cursos.find((c) => c.codigo === codigo);
59 | };
60 |
61 | const getCursosMateria = (codigoMateria) => {
62 | const cursos = horariosSIU?.materias.find(
63 | (m) => m.codigo === codigoMateria
64 | ).cursos;
65 | return cursos?.map(getCurso) || [];
66 | };
67 |
68 | return {
69 | getMateria,
70 | getCurso,
71 | getCursosMateria
72 | };
73 | }, [horariosSIU]);
74 |
75 | // ESTADO 1: Las materias tickeadas por el usuario para verlas en el drawer
76 | const [selectedMaterias, setSelectedMaterias] = useImmer(() =>
77 | initialSelectedMaterias()
78 | );
79 |
80 | // ESTADO 2: Las tabs y el nombre que el usuario les puso
81 | const [activeTabId, setActiveTabId] = React.useState(0);
82 |
83 | const tabsReducer = (draft, action) => {
84 | // eslint-disable-next-line default-case
85 | switch (action.type) {
86 | case "add":
87 | return void draft.push({ id: action.id });
88 | case "rename":
89 | return void (draft.find((t) => t.id === action.id).title =
90 | action.title);
91 | case "remove":
92 | return draft.filter((t) => t.id !== action.id);
93 | }
94 | };
95 |
96 | const [tabs, tabsDispatch] = useImmerReducer(
97 | tabsReducer,
98 | [{ id: 0 }],
99 | initialTabs
100 | );
101 |
102 | // ESTADO 3, el mas importante: Todos los eventos que hay en cada tab
103 | const tabEventsReducer = (draft, action) => {
104 | // eslint-disable-next-line default-case
105 | switch (action.type) {
106 | case "select":
107 | if (getters.getCurso(action.id)) {
108 | if (!draft[activeTabId].cursos.includes(action.id)) {
109 | draft[activeTabId].cursos.push(action.id);
110 | } else {
111 | draft[activeTabId].cursos = draft[activeTabId].cursos.filter(
112 | (i) => i !== action.id
113 | );
114 | }
115 | } else {
116 | if (!draft[activeTabId].extra.includes(action.id)) {
117 | draft[activeTabId].extra.push(action.id);
118 | } else {
119 | draft[activeTabId].extra = draft[activeTabId].extra.filter(
120 | (i) => i !== action.id
121 | );
122 | }
123 | }
124 | return;
125 | case "resetTab":
126 | draft[action.tabId] = { cursos: [], extra: [] };
127 | return;
128 | case "removeTab":
129 | delete draft[action.tabId];
130 | return;
131 | case "removeExtra":
132 | return Object.fromEntries(
133 | Object.entries(draft).map(([tabId, { cursos, extra }]) => [
134 | tabId,
135 | { cursos, extra: extra.filter((i) => i !== action.id) }
136 | ])
137 | );
138 | case "removeCursos":
139 | return Object.fromEntries(
140 | Object.entries(draft).map(([tabId, { cursos, extra }]) => [
141 | tabId,
142 | { cursos: cursos.filter((i) => !action.ids.includes(i)), extra }
143 | ])
144 | );
145 | case "removeAllExtra":
146 | return Object.fromEntries(
147 | Object.entries(draft).map(([tabId, { cursos, _extra }]) => [
148 | tabId,
149 | { cursos, extra: [] }
150 | ])
151 | );
152 | }
153 | };
154 |
155 | const [tabEvents, tabEventsDispatch] = useImmerReducer(
156 | tabEventsReducer,
157 | { 0: { cursos: [], extra: [] } },
158 | (defvalue) => initialTabEvents(defvalue)
159 | );
160 |
161 | // ESTADO 4: Los horarios extracurriculares que agrega el usuario, y el nombre que les puso
162 | const extraEventsReducer = (draft, action) => {
163 | // eslint-disable-next-line default-case
164 | switch (action.type) {
165 | case "add":
166 | return void draft.push({
167 | id: action.event.id,
168 | start: action.event.start,
169 | end: action.event.end,
170 | title: action.event.title
171 | });
172 | case "rename":
173 | return void (draft.find((t) => t.id === action.id).title =
174 | action.title);
175 | case "remove":
176 | return draft.filter((t) => t.id !== action.id);
177 | case "reset":
178 | return [];
179 | }
180 | };
181 |
182 | const [extraEvents, extraEventsDispatch] = useImmerReducer(
183 | extraEventsReducer,
184 | [],
185 | initialExtraEvents
186 | );
187 |
188 | const getPeriodosSIU = (rawdata) => {
189 | let periodos;
190 | try {
191 | periodos = parseSIU(rawdata);
192 | if (!periodos.length) {
193 | throw new Error("No se encontraron horarios en el archivo");
194 | }
195 | } catch (e) {
196 | console.warn(e);
197 | throw new Error("Error al parsear los horarios del SIU");
198 | }
199 | return periodos;
200 | };
201 |
202 | const applyHorariosSIU = (periodo) => {
203 | setHorariosSIU(periodo);
204 | };
205 |
206 | const removeHorariosSIU = async () => {
207 | // Limpiamos todas las materias seleccionadas por el usuario
208 | selectedMaterias.forEach((codigo) => {
209 | toggleMateria(codigo);
210 | });
211 | setHorariosSIU(null);
212 | };
213 |
214 | // El estado que se guarda y determina el permalink es el `savedata` del usuario
215 | const savedata = React.useMemo(() => {
216 | return {
217 | selectedMaterias,
218 | tabEvents,
219 | tabs,
220 | extraEvents,
221 | horariosSIU,
222 | skipSIU,
223 | };
224 | }, [
225 | JSON.stringify(selectedMaterias),
226 | JSON.stringify(tabEvents),
227 | JSON.stringify(tabs),
228 | JSON.stringify(extraEvents),
229 | JSON.stringify(horariosSIU),
230 | JSON.stringify(skipSIU),
231 | ]);
232 |
233 | // Si venimos de un permalink, estamos en una sesion de read - only hasta que el usuario quiera pisar los datos
234 | const [readOnly, setReadOnly] = React.useState(!!permalinksavedata);
235 |
236 | const permalink = React.useMemo(() => {
237 | const savedatab64 = jsontobase64(savedata);
238 | return `https://fede.dm/FIUBA-Plan/#${savedatab64}`;
239 | }, [JSON.stringify(savedata)]);
240 |
241 | React.useEffect(() => {
242 | if (readOnly) return;
243 | window.localStorage.setItem("fiubaplan", JSON.stringify(savedata));
244 | }, [JSON.stringify(savedata), readOnly]);
245 |
246 | // INTERFACES DE CADA ESTADO
247 |
248 | // Tildar/destildar cursos y materias
249 | const toggleMateria = (codigo) => {
250 | if (selectedMaterias.includes(codigo)) {
251 | // Si destildamos una materia, removemos todos sus eventos
252 | const ids = getters.getCursosMateria(codigo).map((c) => c.codigo);
253 | tabEventsDispatch({ type: "removeCursos", ids });
254 | setSelectedMaterias((draft) => draft.filter((i) => i !== codigo));
255 | } else {
256 | // Si tildamos una materia, agregamos el primer curso
257 | toggleCurso(getters.getCursosMateria(codigo)[0].codigo);
258 | setSelectedMaterias((draft) => [...draft, codigo]);
259 | }
260 | };
261 |
262 | const toggleCurso = (codigo) => {
263 | tabEventsDispatch({ type: "select", id: codigo, tabId: activeTabId });
264 | };
265 |
266 | // Agregar, eliminar, renombrar horarios extras
267 | const addExtra = ({ start, end }) => {
268 | // We don't want simple clicks to trigger the creation of an event
269 | // Limiting the time event to at least 60 minutes means the user dragged the mouse, instead of just clicking
270 | const minutes = Math.floor((end - start) / 1000 / 60);
271 | if (minutes < 60) return;
272 |
273 | const id = start.getTime() + end.getTime() + Math.random() * 100;
274 | const randomLetter = String.fromCharCode(
275 | 65 + Math.floor(id % 23) + Math.floor(id % 3)
276 | );
277 | const title = `ACTIVIDAD ${randomLetter}`;
278 |
279 | extraEventsDispatch({ type: "add", event: { start, end, id, title } });
280 | toggleExtra(id);
281 | };
282 |
283 | const toggleExtra = (id) => {
284 | tabEventsDispatch({ type: "select", id });
285 | };
286 |
287 | const removeExtra = (id) => {
288 | if (tabEvents[activeTabId].extra.includes(id)) {
289 | toggleExtra(id);
290 | }
291 | tabEventsDispatch({ type: "removeExtra", id });
292 | extraEventsDispatch({ type: "remove", id });
293 | };
294 |
295 | const removeExtraFromTab = (id) => {
296 | const tabs = Object.values(tabEvents).filter((tab) =>
297 | tab.extra.includes(id)
298 | );
299 | if (tabs.length === 1) {
300 | removeExtra(id);
301 | } else {
302 | toggleExtra(id);
303 | }
304 | };
305 |
306 | const renameExtra = (id, str) => {
307 | extraEventsDispatch({
308 | type: "rename",
309 | id: id,
310 | title: str.trim() || "EXTRA"
311 | });
312 | };
313 |
314 | const removeAllExtra = () => {
315 | tabEventsDispatch({ type: "removeAllExtra" });
316 | extraEventsDispatch({ type: "reset" });
317 | };
318 |
319 | // Agregar, eliminar, renombrar tabs
320 | const limpiarTab = () => {
321 | tabEventsDispatch({ type: "resetTab", tabId: activeTabId });
322 | };
323 |
324 | const selectTab = (id) => {
325 | setActiveTabId(id);
326 | };
327 |
328 | const addTab = () => {
329 | const ids = tabs.map((t) => t.id);
330 | let id = 0;
331 | while (ids.includes(id)) {
332 | id += 1;
333 | }
334 | tabsDispatch({ type: "add", id });
335 | tabEventsDispatch({ type: "resetTab", tabId: id });
336 | selectTab(id);
337 | };
338 |
339 | const renameTab = (id, title) => {
340 | tabsDispatch({ type: "rename", id, title });
341 | };
342 |
343 | const removeTab = (id) => {
344 | selectTab(tabs[tabs.map((t) => t.id).indexOf(id) - 1].id);
345 | tabsDispatch({ type: "remove", id });
346 | tabEventsDispatch({ type: "removeTab", tabId: id });
347 | };
348 |
349 | // Los eventos a mostrar en el calendario son todos los cursos seleccionados por el usuario
350 | // y los horarios extracurriculares que esten presentes en la tab actual
351 | const events = React.useMemo(() => {
352 | const extraevents = tabEvents[activeTabId].extra.map((ev) => {
353 | const event = extraEvents.find((e) => e.id === ev);
354 | const title = event.title;
355 | const subtitle = "ACTIVIDAD EXTRACURRICULAR";
356 | const tooltip = `${title}\n${subtitle}`;
357 |
358 | return {
359 | start: event.start,
360 | end: event.end,
361 | id: event.id,
362 | title,
363 | subtitle,
364 | tooltip,
365 | curso: null
366 | };
367 | });
368 |
369 | const clases = tabEvents[activeTabId].cursos
370 | .map(getters.getCurso)
371 | .flatMap((curso) => {
372 | const materia = getters.getMateria(curso.materia);
373 | return curso.clases.map((clase) => {
374 | const inicio = new Date(2018, 0, clase.dia);
375 | const [inicioHora, inicioMinutos] = clase.inicio.split(":");
376 | inicio.setHours(inicioHora, inicioMinutos);
377 | const fin = new Date(2018, 0, clase.dia);
378 | const [finHora, finMinutos] = clase.fin.split(":");
379 | fin.setHours(finHora, finMinutos);
380 | const title = `[${materia.codigo}] ${materia.nombre}`;
381 | const subtitle = curso.docentes;
382 | const tooltip = `[${materia.codigo}] ${materia.nombre}\n${curso.docentes}`;
383 |
384 | return {
385 | start: inicio,
386 | end: fin,
387 | id: curso.clases + curso.codigo + curso.docentes,
388 | title,
389 | subtitle,
390 | tooltip,
391 | curso: curso.codigo
392 | };
393 | });
394 | });
395 |
396 | if (extraEvents.length === 0) return clases;
397 | return [...clases, ...extraevents];
398 | }, [activeTabId, extraEvents, JSON.stringify(tabEvents)]);
399 |
400 | return {
401 | selectedMaterias,
402 | activeTabId,
403 | tabs,
404 | extraEvents,
405 | readOnly,
406 | setReadOnly,
407 | permalink,
408 | toggleMateria,
409 | toggleCurso,
410 | addExtra,
411 | toggleExtra,
412 | removeExtra,
413 | removeExtraFromTab,
414 | renameExtra,
415 | removeAllExtra,
416 | limpiarTab,
417 | selectTab,
418 | addTab,
419 | renameTab,
420 | removeTab,
421 | events,
422 | horariosSIU,
423 | applyHorariosSIU,
424 | removeHorariosSIU,
425 | getters,
426 | getPeriodosSIU,
427 | errorPermalink,
428 | setErrorPermalink,
429 | skipSIU,
430 | setSkipSIU
431 | };
432 | };
433 |
434 | const getFromStorage = (key) => {
435 | const json = JSON.parse(window.localStorage.getItem("fiubaplan"));
436 | return json?.[key];
437 | };
438 |
439 | // STATE INITIALIZERS: le pasamos una funcion a useState/useReducer/useImmer/useImmerReducer para evitar que se ejecuten en cada render
440 | const initialSelectedMaterias = () => {
441 | return (
442 | permalinksavedata?.selectedMaterias ||
443 | getFromStorage("selectedMaterias") ||
444 | []
445 | );
446 | };
447 |
448 | const initialTabs = (defvalue) => {
449 | return permalinksavedata?.tabs || getFromStorage("tabs") || defvalue;
450 | };
451 |
452 | const initialTabEvents = (defvalue) => {
453 | const tabEvents =
454 | permalinksavedata?.tabEvents || getFromStorage("tabEvents") || defvalue;
455 | return Object.fromEntries(
456 | Object.entries(tabEvents).map(([tabid, { cursos, extra }]) => [
457 | tabid,
458 | { cursos: cursos, extra }
459 | ])
460 | );
461 | };
462 |
463 | const initialExtraEvents = (defvalue) => {
464 | const coerceExtraEvent = (e) => ({
465 | ...e,
466 | start: new Date(e.start),
467 | end: new Date(e.end)
468 | });
469 | return (
470 | permalinksavedata?.extraEvents?.map(coerceExtraEvent) ||
471 | getFromStorage("extraEvents")?.map(coerceExtraEvent) ||
472 | defvalue
473 | );
474 | };
475 |
476 | const initialHorariosSIU = () => {
477 | return (
478 | permalinksavedata?.horariosSIU || getFromStorage("horariosSIU") || null
479 | );
480 | };
481 |
--------------------------------------------------------------------------------
/tests/siu-json/siu-exactas-computacion-primer-cuatri.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "periodo": "2024 - Verano",
4 | "materias": [
5 | {
6 | "nombre": "Análisis I",
7 | "codigo": "COMP230003",
8 | "cursos": ["COMP230003-Análisis I"]
9 | },
10 | {
11 | "nombre": "Álgebra I",
12 | "codigo": "COMP930001",
13 | "cursos": ["COMP930001-Algebra I"]
14 | }
15 | ],
16 | "cursos": [
17 | {
18 | "materia": "COMP230003",
19 | "codigo": "COMP230003-Análisis I",
20 | "docentes": "Balderrama Rocío Celeste ",
21 | "clases": [
22 | { "dia": 1, "inicio": "09:00", "fin": "11:15" },
23 | { "dia": 2, "inicio": "09:00", "fin": "11:15" },
24 | { "dia": 4, "inicio": "09:00", "fin": "11:15" },
25 | { "dia": 5, "inicio": "09:00", "fin": "11:15" },
26 | { "dia": 1, "inicio": "11:15", "fin": "14:30" },
27 | { "dia": 2, "inicio": "11:15", "fin": "14:30" },
28 | { "dia": 4, "inicio": "11:15", "fin": "14:30" },
29 | { "dia": 5, "inicio": "11:15", "fin": "14:30" }
30 | ]
31 | },
32 | {
33 | "materia": "COMP930001",
34 | "codigo": "COMP930001-Algebra I",
35 | "docentes": "Cesaratto Eda ",
36 | "clases": [
37 | { "dia": 1, "inicio": "09:00", "fin": "11:15" },
38 | { "dia": 2, "inicio": "09:00", "fin": "11:15" },
39 | { "dia": 4, "inicio": "09:00", "fin": "11:15" },
40 | { "dia": 5, "inicio": "09:00", "fin": "11:15" },
41 | { "dia": 1, "inicio": "11:15", "fin": "14:30" },
42 | { "dia": 2, "inicio": "11:15", "fin": "14:30" },
43 | { "dia": 4, "inicio": "11:15", "fin": "14:30" },
44 | { "dia": 5, "inicio": "11:15", "fin": "14:30" }
45 | ]
46 | }
47 | ],
48 | "timestamp": 1710968375377
49 | },
50 | {
51 | "periodo": "2024 - 1er. Cuatrimestre",
52 | "materias": [
53 | {
54 | "nombre": "Algoritmos y Estructuras de Datos",
55 | "codigo": "COMP230001",
56 | "cursos": ["COMP230001-AED Turno Mañana", "COMP230001-AED Turno Noche"]
57 | },
58 | {
59 | "nombre": "Análisis I",
60 | "codigo": "COMP230003",
61 | "cursos": ["COMP230003-Análisis I"]
62 | },
63 | {
64 | "nombre": "Aprendizaje Automático 2024",
65 | "codigo": "COMP930656",
66 | "cursos": ["COMP930656-A"]
67 | },
68 | {
69 | "nombre": "Aprendizaje Automático en Grafos",
70 | "codigo": "COMP930663",
71 | "cursos": ["COMP930663-A"]
72 | },
73 | {
74 | "nombre": "Fundamentos de Artificial General Intelligence Safety",
75 | "codigo": "COMP930657",
76 | "cursos": ["COMP930657-A"]
77 | },
78 | {
79 | "nombre": "Introducción a la Programación",
80 | "codigo": "COMP230008",
81 | "cursos": [
82 | "COMP230008-A",
83 | "COMP230008-B",
84 | "COMP230008-C",
85 | "COMP230008-D"
86 | ]
87 | },
88 | {
89 | "nombre": "Modelado y Análisis de Sistemas Reactivos y Concurrentes",
90 | "codigo": "COMP931252",
91 | "cursos": ["COMP931252-A"]
92 | },
93 | {
94 | "nombre": "Modelado y Simulación de Sistemas Complejos con Aplicaciones en Economía",
95 | "codigo": "COMP930658",
96 | "cursos": ["COMP930658-A"]
97 | },
98 | {
99 | "nombre": "Paradigmas de Programación",
100 | "codigo": "COMP930015",
101 | "cursos": ["COMP930015-A"]
102 | },
103 | {
104 | "nombre": "Procesamiento Avanzado de Señales 2024",
105 | "codigo": "COMP930668",
106 | "cursos": ["COMP930668-A"]
107 | },
108 | {
109 | "nombre": "Procesamiento de Lenguaje Natural",
110 | "codigo": "COMP930662",
111 | "cursos": ["COMP930662-A"]
112 | },
113 | {
114 | "nombre": "Redes, Sociedad y Economía",
115 | "codigo": "COMP931538",
116 | "cursos": ["COMP931538-A"]
117 | },
118 | {
119 | "nombre": "Seguridad de la Información",
120 | "codigo": "COMP931324",
121 | "cursos": ["COMP931324-A"]
122 | },
123 | {
124 | "nombre": "Sistemas Digitales",
125 | "codigo": "COMP230014",
126 | "cursos": ["COMP230014-Turno Mañana", "COMP230014-Turno Noche"]
127 | },
128 | {
129 | "nombre": "Sistemas Operativos",
130 | "codigo": "COMP930017",
131 | "cursos": ["COMP930017-A"]
132 | },
133 | {
134 | "nombre": "Taller de Tesis I",
135 | "codigo": "COMP930660",
136 | "cursos": ["COMP930660-A"]
137 | },
138 | {
139 | "nombre": "Teoría de Juegos (DC) 2024",
140 | "codigo": "COMP930666",
141 | "cursos": ["COMP930666-A"]
142 | },
143 | {
144 | "nombre": "Técnicas de Diseño de Algoritmos",
145 | "codigo": "COMP230015",
146 | "cursos": ["COMP230015-A"]
147 | },
148 | {
149 | "nombre": "Álgebra I",
150 | "codigo": "COMP930001",
151 | "cursos": ["COMP930001-Algebra I"]
152 | },
153 | {
154 | "nombre": "Álgebra Lineal Computacional",
155 | "codigo": "LCDA210006",
156 | "cursos": ["LCDA210006-Algebra lineal computacional"]
157 | }
158 | ],
159 | "cursos": [
160 | {
161 | "materia": "COMP230001",
162 | "codigo": "COMP230001-AED Turno Mañana",
163 | "docentes": "Braberman Victor Adrian , Tcach Lufrano Alexis Guido , Bendersky Diego Ariel , Bianchi Bruno , González Mariano Martín , Dubinsky Manuel , Landfried Gustavo Andrés , Schitter Tomas Jose , Travi Fermin , Gonzalez Omahen Augusto Ezequiel , Ramirez Leandro Jesús , Semeria Camilo ",
164 | "clases": [
165 | { "dia": 2, "inicio": "09:00", "fin": "14:00" },
166 | { "dia": 3, "inicio": "09:00", "fin": "14:00" },
167 | { "dia": 5, "inicio": "09:00", "fin": "14:00" }
168 | ]
169 | },
170 | {
171 | "materia": "COMP230001",
172 | "codigo": "COMP230001-AED Turno Noche",
173 | "docentes": "Garbervetsky Diego David , Bianchi Bruno , Carreira Munich Tobias Agustin , Cerdeira Elías Nahuel , González Mariano Martín , Dandois Santiago José , Gastron Matias Ezequiel , Maqueda Ignacio , Capelo Gianluca , Gorojovsky Roman , Sawczuk Nicolás Iván ",
174 | "clases": [
175 | { "dia": 2, "inicio": "17:00", "fin": "22:00" },
176 | { "dia": 3, "inicio": "17:00", "fin": "22:00" },
177 | { "dia": 5, "inicio": "17:00", "fin": "22:00" }
178 | ]
179 | },
180 | {
181 | "materia": "COMP230003",
182 | "codigo": "COMP230003-Análisis I",
183 | "docentes": "Larotonda Gabriel Andrés ",
184 | "clases": [
185 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
186 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
187 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
188 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
189 | { "dia": 1, "inicio": "11:00", "fin": "14:00" },
190 | { "dia": 4, "inicio": "11:00", "fin": "14:00" },
191 | { "dia": 1, "inicio": "11:00", "fin": "14:00" },
192 | { "dia": 4, "inicio": "11:00", "fin": "14:00" },
193 | { "dia": 1, "inicio": "14:00", "fin": "16:00" },
194 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
195 | { "dia": 1, "inicio": "16:00", "fin": "19:00" },
196 | { "dia": 4, "inicio": "16:00", "fin": "19:00" },
197 | { "dia": 1, "inicio": "17:00", "fin": "19:00" },
198 | { "dia": 4, "inicio": "17:00", "fin": "19:00" },
199 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
200 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
201 | ]
202 | },
203 | {
204 | "materia": "COMP930656",
205 | "codigo": "COMP930656-A",
206 | "docentes": "Brusco Pablo ",
207 | "clases": [
208 | { "dia": 2, "inicio": "17:00", "fin": "21:00" },
209 | { "dia": 4, "inicio": "17:00", "fin": "21:00" }
210 | ]
211 | },
212 | {
213 | "materia": "COMP930663",
214 | "codigo": "COMP930663-A",
215 | "docentes": "Lombardi Leandro Ezequiel ",
216 | "clases": [
217 | { "dia": 1, "inicio": "09:30", "fin": "12:30" },
218 | { "dia": 5, "inicio": "09:00", "fin": "11:00" }
219 | ]
220 | },
221 | {
222 | "materia": "COMP930657",
223 | "codigo": "COMP930657-A",
224 | "docentes": "Abriola Sergio Alejandro ",
225 | "clases": [{ "dia": 5, "inicio": "17:00", "fin": "21:00" }]
226 | },
227 | {
228 | "materia": "COMP230008",
229 | "codigo": "COMP230008-A",
230 | "docentes": "De Cristoforis Pablo Esteban , Di Piazza Gabriela Melisa , Godoy Javier Ignacio , González Mariano Martín , Rubinstein Pablo Andres , Sansone Agustín , Tilli Dora Elena , Bekenstein Jonathan Ezequiel , Bustamante Luis Ricardo , Mamani Fernandez Jorge Ricardo , Perez Bianchi Paula ",
231 | "clases": [
232 | { "dia": 1, "inicio": "09:00", "fin": "11:30" },
233 | { "dia": 3, "inicio": "09:00", "fin": "11:30" },
234 | { "dia": 4, "inicio": "09:00", "fin": "14:00" }
235 | ]
236 | },
237 | {
238 | "materia": "COMP230008",
239 | "codigo": "COMP230008-B",
240 | "docentes": "De Cristoforis Pablo Esteban , Di Piazza Gabriela Melisa , Godoy Javier Ignacio , González Mariano Martín , Rubinstein Pablo Andres , Sansone Agustín , Tilli Dora Elena , Bekenstein Jonathan Ezequiel , Bustamante Luis Ricardo , Mamani Fernandez Jorge Ricardo , Perez Bianchi Paula ",
241 | "clases": [
242 | { "dia": 1, "inicio": "11:30", "fin": "14:00" },
243 | { "dia": 3, "inicio": "11:30", "fin": "14:00" },
244 | { "dia": 4, "inicio": "09:00", "fin": "14:00" }
245 | ]
246 | },
247 | {
248 | "materia": "COMP230008",
249 | "codigo": "COMP230008-C",
250 | "docentes": "Altauz Javier Hernán , Urtasun Martín , Brassesco Maria Virginia , Dengra Silvina , González Mariano Martín , Benedetti Juan Pablo , Romano Francisco , Vasulka Mariano , Vita Sebastian Alberto , Lew Deveali Simon , Ocampo Debora Daiana ",
251 | "clases": [
252 | { "dia": 4, "inicio": "17:00", "fin": "22:00" },
253 | { "dia": 1, "inicio": "17:00", "fin": "19:30" },
254 | { "dia": 3, "inicio": "17:00", "fin": "19:30" }
255 | ]
256 | },
257 | {
258 | "materia": "COMP230008",
259 | "codigo": "COMP230008-D",
260 | "docentes": "Altauz Javier Hernán , Urtasun Martín , Brassesco Maria Virginia , Dengra Silvina , González Mariano Martín , Benedetti Juan Pablo , Romano Francisco , Vasulka Mariano , Vita Sebastian Alberto , Lew Deveali Simon , Ocampo Debora Daiana ",
261 | "clases": [
262 | { "dia": 1, "inicio": "19:30", "fin": "22:00" },
263 | { "dia": 3, "inicio": "19:30", "fin": "22:00" },
264 | { "dia": 4, "inicio": "17:00", "fin": "22:00" }
265 | ]
266 | },
267 | {
268 | "materia": "COMP931252",
269 | "codigo": "COMP931252-A",
270 | "docentes": "Uchitel Sebastian ",
271 | "clases": [
272 | { "dia": 2, "inicio": "09:00", "fin": "13:00" },
273 | { "dia": 4, "inicio": "10:00", "fin": "12:00" }
274 | ]
275 | },
276 | {
277 | "materia": "COMP930658",
278 | "codigo": "COMP930658-A",
279 | "docentes": "Castro Rodrigo Daniel ",
280 | "clases": [
281 | { "dia": 1, "inicio": "17:00", "fin": "19:00" },
282 | { "dia": 1, "inicio": "19:00", "fin": "21:00" }
283 | ]
284 | },
285 | {
286 | "materia": "COMP930015",
287 | "codigo": "COMP930015-A",
288 | "docentes": "Barenbaum Pablo , Cossio Mercado Christian Gustavo , Marottoli Daniela , Steren Gabriela , Díaz Caro Alejandro ",
289 | "clases": [
290 | { "dia": 2, "inicio": "17:00", "fin": "22:00" },
291 | { "dia": 5, "inicio": "17:00", "fin": "22:00" },
292 | { "dia": 2, "inicio": "17:00", "fin": "22:00" },
293 | { "dia": 5, "inicio": "17:00", "fin": "22:00" }
294 | ]
295 | },
296 | {
297 | "materia": "COMP930668",
298 | "codigo": "COMP930668-A",
299 | "docentes": "Risk Marcelo Raul ",
300 | "clases": [
301 | { "dia": 2, "inicio": "17:00", "fin": "18:00" },
302 | { "dia": 2, "inicio": "18:00", "fin": "20:00" }
303 | ]
304 | },
305 | {
306 | "materia": "COMP930662",
307 | "codigo": "COMP930662-A",
308 | "docentes": "Del Corro Luciano Manuel ",
309 | "clases": [{ "dia": 2, "inicio": "09:00", "fin": "12:00" }]
310 | },
311 | {
312 | "materia": "COMP931538",
313 | "codigo": "COMP931538-A",
314 | "docentes": "Feuerstein Esteban Zindel ",
315 | "clases": [{ "dia": 2, "inicio": "17:15", "fin": "21:15" }]
316 | },
317 | {
318 | "materia": "COMP931324",
319 | "codigo": "COMP931324-A",
320 | "docentes": "Baader Rodolfo Pablo ",
321 | "clases": [
322 | { "dia": 1, "inicio": "18:00", "fin": "20:30" },
323 | { "dia": 3, "inicio": "18:00", "fin": "20:30" }
324 | ]
325 | },
326 | {
327 | "materia": "COMP230014",
328 | "codigo": "COMP230014-Turno Mañana",
329 | "docentes": "Buemi María Elena , Cerrutti Mariano Javier , Bekenstein Jonathan Ezequiel , Siciliani Andres , Sánchez Posadas Ramiro ",
330 | "clases": [
331 | { "dia": 4, "inicio": "08:00", "fin": "10:00" },
332 | { "dia": 4, "inicio": "10:00", "fin": "13:00" }
333 | ]
334 | },
335 | {
336 | "materia": "COMP230014",
337 | "codigo": "COMP230014-Turno Noche",
338 | "docentes": "Buemi María Elena , Zoppi Edgardo Julio , Raffo Diego Martín , Gonzalez Omahen Augusto Ezequiel , Romani Rafael ",
339 | "clases": [
340 | { "dia": 4, "inicio": "17:00", "fin": "19:00" },
341 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
342 | ]
343 | },
344 | {
345 | "materia": "COMP930017",
346 | "codigo": "COMP930017-A",
347 | "docentes": "Fernandez Slezak Diego , Sumoza Matos Rodolfo Leonardo ",
348 | "clases": [
349 | { "dia": 2, "inicio": "17:00", "fin": "21:00" },
350 | { "dia": 4, "inicio": "17:00", "fin": "21:00" },
351 | { "dia": 2, "inicio": "17:00", "fin": "21:00" },
352 | { "dia": 4, "inicio": "17:00", "fin": "21:00" }
353 | ]
354 | },
355 | {
356 | "materia": "COMP930660",
357 | "codigo": "COMP930660-A",
358 | "docentes": "Kamienkowski Juan Esteban ",
359 | "clases": [{ "dia": 1, "inicio": "17:00", "fin": "22:00" }]
360 | },
361 | {
362 | "materia": "COMP930666",
363 | "codigo": "COMP930666-A",
364 | "docentes": "Arbiser Ariel ",
365 | "clases": [{ "dia": 3, "inicio": "14:30", "fin": "19:00" }]
366 | },
367 | {
368 | "materia": "COMP230015",
369 | "codigo": "COMP230015-A",
370 | "docentes": "Bonomo Flavia , Soulignac Francisco Juan , Terlisky Pablo Ezequiel , Braier Julián , Amster Martín , Umfurer Alfredo Raul ",
371 | "clases": [
372 | { "dia": 1, "inicio": "09:00", "fin": "13:00" },
373 | { "dia": 3, "inicio": "09:00", "fin": "13:00" },
374 | { "dia": 1, "inicio": "17:00", "fin": "21:00" },
375 | { "dia": 3, "inicio": "17:00", "fin": "21:00" }
376 | ]
377 | },
378 | {
379 | "materia": "COMP930001",
380 | "codigo": "COMP930001-Algebra I",
381 | "docentes": "Zadunaisky Bustillos Pablo Mauricio , Merzbacher Diego Mariano , Antunes Percincula Carlos Santiago , Rufolo Franco Nicolás ",
382 | "clases": [
383 | { "dia": 2, "inicio": "09:00", "fin": "14:00" },
384 | { "dia": 5, "inicio": "09:00", "fin": "14:00" },
385 | { "dia": 2, "inicio": "09:00", "fin": "14:00" },
386 | { "dia": 5, "inicio": "09:00", "fin": "14:00" },
387 | { "dia": 2, "inicio": "14:00", "fin": "19:00" },
388 | { "dia": 5, "inicio": "14:00", "fin": "19:00" },
389 | { "dia": 2, "inicio": "17:00", "fin": "22:00" },
390 | { "dia": 5, "inicio": "17:00", "fin": "22:00" }
391 | ]
392 | },
393 | {
394 | "materia": "LCDA210006",
395 | "codigo": "LCDA210006-Algebra lineal computacional",
396 | "docentes": "Martinez Sandra Rita ",
397 | "clases": [
398 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
399 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
400 | { "dia": 2, "inicio": "11:00", "fin": "14:00" },
401 | { "dia": 4, "inicio": "11:00", "fin": "14:00" }
402 | ]
403 | }
404 | ],
405 | "timestamp": 1710968375606
406 | },
407 | {
408 | "periodo": "2024 - 1er. Bimestre",
409 | "materias": [
410 | {
411 | "nombre": "Aprendizaje Profundo - VISIT2024",
412 | "codigo": "COMP930671",
413 | "cursos": ["COMP930671-A"]
414 | },
415 | {
416 | "nombre": "Criptografía Moderna - VISIT2024",
417 | "codigo": "COMP930669",
418 | "cursos": ["COMP930669-A"]
419 | },
420 | {
421 | "nombre": "Introducción a las APIs - VISIT2024",
422 | "codigo": "COMP930670",
423 | "cursos": ["COMP930670-A"]
424 | },
425 | {
426 | "nombre": "Modelado y Análisis de Sistemas Reactivos y Concurrentes",
427 | "codigo": "COMP931252",
428 | "cursos": ["COMP931252-A"]
429 | },
430 | {
431 | "nombre": "Procesamiento de Imágenes Cerebrales a Gran Escala con Aplicaciones de Machine Learning - VISIT2024",
432 | "codigo": "COMP930673",
433 | "cursos": ["COMP930673-A"]
434 | },
435 | {
436 | "nombre": "Seminario de Demostración Automática 2024",
437 | "codigo": "COMP930664",
438 | "cursos": ["COMP930664-A"]
439 | }
440 | ],
441 | "cursos": [
442 | {
443 | "materia": "COMP930671",
444 | "codigo": "COMP930671-A",
445 | "docentes": "Ferrante Enzo , Rodriguez Ricardo Oscar ",
446 | "clases": [{ "dia": 2, "inicio": "09:00", "fin": "12:00" }]
447 | },
448 | {
449 | "materia": "COMP930669",
450 | "codigo": "COMP930669-A",
451 | "docentes": "Rodriguez Ricardo Oscar ",
452 | "clases": [
453 | { "dia": 2, "inicio": "14:00", "fin": "17:00" },
454 | { "dia": 4, "inicio": "14:00", "fin": "17:00" }
455 | ]
456 | },
457 | {
458 | "materia": "COMP930670",
459 | "codigo": "COMP930670-A",
460 | "docentes": "De Caso Guido ",
461 | "clases": [{ "dia": 3, "inicio": "17:00", "fin": "20:00" }]
462 | },
463 | {
464 | "materia": "COMP931252",
465 | "codigo": "COMP931252-A",
466 | "docentes": "Uchitel Sebastian ",
467 | "clases": [
468 | { "dia": 2, "inicio": "09:00", "fin": "13:00" },
469 | { "dia": 4, "inicio": "10:00", "fin": "12:00" }
470 | ]
471 | },
472 | {
473 | "materia": "COMP930673",
474 | "codigo": "COMP930673-A",
475 | "docentes": "Rodriguez Ricardo Oscar ",
476 | "clases": [
477 | { "dia": 1, "inicio": "09:00", "fin": "13:00" },
478 | { "dia": 2, "inicio": "09:00", "fin": "13:00" },
479 | { "dia": 3, "inicio": "09:00", "fin": "13:00" },
480 | { "dia": 4, "inicio": "09:00", "fin": "13:00" },
481 | { "dia": 5, "inicio": "09:00", "fin": "13:00" }
482 | ]
483 | },
484 | {
485 | "materia": "COMP930664",
486 | "codigo": "COMP930664-A",
487 | "docentes": "Rodriguez Ricardo Oscar ",
488 | "clases": [{ "dia": 3, "inicio": "14:00", "fin": "17:00" }]
489 | }
490 | ],
491 | "timestamp": 1710968375647
492 | }
493 | ]
494 |
--------------------------------------------------------------------------------
/tests/siu-raw/siu-exactas-computacion-primer-cuatri.js:
--------------------------------------------------------------------------------
1 | export const siuExactasRaw = `
2 | 4
3 | 0
4 | Nombre Falso
5 | Propuesta: Licenciatura en ciencias de la computaci...
6 | Inicio
7 | Inscripción a Materias
8 | Inscripción a Exámenes
9 | Reportes
10 | Encuestas
11 | Trámites
12 | Perfil: Alumno
13 | Oferta de comisiones
14 | Filtros
15 | LunesMartesMiércolesJuevesViernesSábadoDomingoSin definir
16 | Período lectivo:
17 | Todos
18 | Actividad:
19 | Todas
20 |
21 | Docente:
22 | Todos
23 | Ubicacion:
24 | Todas
25 | Período lectivo: 2024 - Verano
26 | Actividad: Análisis I (COMP230003)
27 | Comisión: Análisis I
28 | Turno: Sin definir
29 | Instancias: Regularidad
30 | Ubicación: Ciudad Universitaria
31 | Subcomisión: Teórica
32 | Cupo / insc.: Sin definir / 26
33 | Docentes: Balderrama Rocío Celeste (Profesor)
34 | Tipo de clase Día Horario Aula
35 | Teórico Lunes 09:00 a 11:15 Aula a determinar
36 | Teórico Martes 09:00 a 11:15 Aula a determinar
37 | Teórico Jueves 09:00 a 11:15 Aula a determinar
38 | Teórico Viernes 09:00 a 11:15 Aula a determinar
39 | Subcomisión: Práctica
40 | Cupo / insc.: Sin definir / 26
41 | Docentes: Santillan Osvaldo Pablo (Jefe de TP), Choque Federico Tomás (Ayudante de 1ra), Beck Fiorella Sol (Ayudante de 2da), Polasek Iván (Ayudante de 2da)
42 | Tipo de clase Día Horario Aula
43 | Práctica Lunes 11:15 a 14:30 Aula a determinar
44 | Práctica Martes 11:15 a 14:30 Aula a determinar
45 | Práctica Jueves 11:15 a 14:30 Aula a determinar
46 | Práctica Viernes 11:15 a 14:30 Aula a determinar
47 | Actividad: Álgebra I (COMP930001)
48 | Comisión: Algebra I
49 | Turno: Sin definir
50 | Instancias: Regularidad
51 | Ubicación: Ciudad Universitaria
52 | Subcomisión: Teórica
53 | Cupo / insc.: Sin definir / 143
54 | Docentes: Cesaratto Eda (Profesor)
55 | Tipo de clase Día Horario Aula
56 | Teórico Lunes 09:00 a 11:15 Aula a determinar
57 | Teórico Martes 09:00 a 11:15 Aula a determinar
58 | Teórico Jueves 09:00 a 11:15 Aula a determinar
59 | Teórico Viernes 09:00 a 11:15 Aula a determinar
60 | Subcomisión: Práctica
61 | Cupo / insc.: Sin definir / 143
62 | Docentes: Busolini Lucía (Jefe de TP), Pin Baque Edwin (Ayudante de 1ra), Duhau Cecilia Noemi (Ayudante de 2da), Nores Manuel Enrique (Ayudante de 2da)
63 | Tipo de clase Día Horario Aula
64 | Práctica Lunes 11:15 a 14:30 Aula a determinar
65 | Práctica Martes 11:15 a 14:30 Aula a determinar
66 | Práctica Jueves 11:15 a 14:30 Aula a determinar
67 | Práctica Viernes 11:15 a 14:30 Aula a determinar
68 | Período lectivo: 2024 - 1er. Cuatrimestre
69 | Actividad: Algoritmos y Estructuras de Datos (COMP230001)
70 | Comisión: AED Turno Mañana
71 | Turno: Mañana
72 | Instancias: Regularidad
73 | Ubicación: Ciudad Universitaria
74 | Subcomisión: AED TM Teórico
75 | Cupo / insc.: Sin definir / 95
76 | Docentes: Braberman Victor Adrian (Profesor), Tcach Lufrano Alexis Guido (Profesor), Bendersky Diego Ariel (Jefe de TP), Bianchi Bruno (Jefe de TP), González Mariano Martín (Jefe de TP), Dubinsky Manuel (Ayudante de 1ra), Landfried Gustavo Andrés (Ayudante de 1ra), Schitter Tomas Jose (Ayudante de 1ra), Travi Fermin (Ayudante de 1ra), Gonzalez Omahen Augusto Ezequiel (Ayudante de 2da), Ramirez Leandro Jesús (Ayudante de 2da), Semeria Camilo (Ayudante de 2da)
77 | Tipo de clase Día Horario Aula
78 | Teórico Martes 09:00 a 14:00 Aula a determinar
79 | Subcomisión: AED TM Práctica
80 | Cupo / insc.: Sin definir / 95
81 | Docentes: Braberman Victor Adrian (Profesor), Tcach Lufrano Alexis Guido (Profesor), Bendersky Diego Ariel (Jefe de TP), Bianchi Bruno (Jefe de TP), González Mariano Martín (Jefe de TP), Dubinsky Manuel (Ayudante de 1ra), Landfried Gustavo Andrés (Ayudante de 1ra), Schitter Tomas Jose (Ayudante de 1ra), Travi Fermin (Ayudante de 1ra), Gonzalez Omahen Augusto Ezequiel (Ayudante de 2da), Ramirez Leandro Jesús (Ayudante de 2da), Semeria Camilo (Ayudante de 2da)
82 | Tipo de clase Día Horario Aula
83 | Práctica Miércoles 09:00 a 14:00 Aula a determinar
84 | Subcomisión: AEDI TM Laboratorio
85 | Cupo / insc.: Sin definir / 95
86 | Docentes: Braberman Victor Adrian (Profesor), Tcach Lufrano Alexis Guido (Profesor), Bendersky Diego Ariel (Jefe de TP), Bianchi Bruno (Jefe de TP), González Mariano Martín (Jefe de TP), Dubinsky Manuel (Ayudante de 1ra), Landfried Gustavo Andrés (Ayudante de 1ra), Schitter Tomas Jose (Ayudante de 1ra), Travi Fermin (Ayudante de 1ra), Gonzalez Omahen Augusto Ezequiel (Ayudante de 2da), Ramirez Leandro Jesús (Ayudante de 2da), Semeria Camilo (Ayudante de 2da)
87 | Tipo de clase Día Horario Aula
88 | Laboratorio Viernes 09:00 a 14:00 Aula a determinar
89 | Comisión: AED Turno Noche
90 | Turno: Noche
91 | Instancias: Regularidad
92 | Ubicación: Ciudad Universitaria
93 | Subcomisión: AED TN Teórico
94 | Cupo / insc.: Sin definir / 58
95 | Docentes: Garbervetsky Diego David (Profesor), Bianchi Bruno (Jefe de TP), Carreira Munich Tobias Agustin (Jefe de TP), Cerdeira Elías Nahuel (Jefe de TP), González Mariano Martín (Jefe de TP), Dandois Santiago José (Ayudante de 1ra), Gastron Matias Ezequiel (Ayudante de 1ra), Maqueda Ignacio (Ayudante de 1ra), Capelo Gianluca (Ayudante de 2da), Gorojovsky Roman (Ayudante de 2da), Sawczuk Nicolás Iván (Ayudante de 2da)
96 | Tipo de clase Día Horario Aula
97 | Teórico Martes 17:00 a 22:00 Aula a determinar
98 | Subcomisión: AED TN Práctica
99 | Cupo / insc.: Sin definir / 58
100 | Docentes: Garbervetsky Diego David (Profesor), Bianchi Bruno (Jefe de TP), Carreira Munich Tobias Agustin (Jefe de TP), Cerdeira Elías Nahuel (Jefe de TP), González Mariano Martín (Jefe de TP), Dandois Santiago José (Ayudante de 1ra), Gastron Matias Ezequiel (Ayudante de 1ra), Maqueda Ignacio (Ayudante de 1ra), Capelo Gianluca (Ayudante de 2da), Gorojovsky Roman (Ayudante de 2da), Sawczuk Nicolás Iván (Ayudante de 2da)
101 | Tipo de clase Día Horario Aula
102 | Práctica Miércoles 17:00 a 22:00 Aula a determinar
103 | Subcomisión: AED TN Laboratorio
104 | Cupo / insc.: Sin definir / 58
105 | Docentes: Garbervetsky Diego David (Profesor), Bianchi Bruno (Jefe de TP), Carreira Munich Tobias Agustin (Jefe de TP), Cerdeira Elías Nahuel (Jefe de TP), González Mariano Martín (Jefe de TP), Dandois Santiago José (Ayudante de 1ra), Gastron Matias Ezequiel (Ayudante de 1ra), Maqueda Ignacio (Ayudante de 1ra), Capelo Gianluca (Ayudante de 2da), Gorojovsky Roman (Ayudante de 2da), Sawczuk Nicolás Iván (Ayudante de 2da)
106 | Tipo de clase Día Horario Aula
107 | Laboratorio Viernes 17:00 a 22:00 Aula a determinar
108 | Actividad: Análisis I (COMP230003)
109 | Comisión: Análisis I
110 | Turno: Sin definir
111 | Instancias: Regularidad/Promoción
112 | Ubicación: Ciudad Universitaria
113 | Subcomisión: Teórica 1 (A-K)
114 | Cupo / insc.: Sin definir / 43
115 | Docentes: Larotonda Gabriel Andrés (Profesor)
116 | Tipo de clase Día Horario Aula
117 | Teórico Lunes 09:00 a 11:00 Aula a determinar
118 | Teórico Jueves 09:00 a 11:00 Aula a determinar
119 | Subcomisión: Teórica 2 (L-Z)
120 | Cupo / insc.: Sin definir / 23
121 | Docentes: Kuna Mariel Paula (Profesor)
122 | Tipo de clase Día Horario Aula
123 | Teórico Lunes 09:00 a 11:00 Aula a determinar
124 | Teórico Jueves 09:00 a 11:00 Aula a determinar
125 | Subcomisión: Práctica 1 (A-K)
126 | Cupo / insc.: Sin definir / 44
127 | Docentes: Menconi Juan Manuel (Jefe de TP), Bianchi Hilde Lida (Ayudante de 1ra), Zhang Fan (Ayudante de 1ra), ALVAREZ Sergio (Ayudante de 2da)
128 | Tipo de clase Día Horario Aula
129 | Práctica Lunes 11:00 a 14:00 Aula a determinar
130 | Práctica Jueves 11:00 a 14:00 Aula a determinar
131 | Subcomisión: Práctica 2 (L-Z)
132 | Cupo / insc.: Sin definir / 25
133 | Docentes: Arcodia Marcos Ramiro Alfredo (Jefe de TP), Singer Joaquín (Jefe de TP), Cañizares Solis Ana Mariela (Ayudante de 1ra), Carraux Gonzalo Adrián (Ayudante de 2da), Mastropietro Bruno Federico (Ayudante de 2da)
134 | Tipo de clase Día Horario Aula
135 | Práctica Lunes 11:00 a 14:00 Aula a determinar
136 | Práctica Jueves 11:00 a 14:00 Aula a determinar
137 | Subcomisión: Teórica 3
138 | Cupo / insc.: Sin definir / 35
139 | Docentes: Paternostro Victoria (Profesor)
140 | Tipo de clase Día Horario Aula
141 | Teórico Lunes 14:00 a 16:00 Aula a determinar
142 | Teórico Jueves 14:00 a 16:00 Aula a determinar
143 | Subcomisión: Práctica 3
144 | Cupo / insc.: Sin definir / 32
145 | Docentes: Villafañe Norberto Román (Jefe de TP), Carabajal Gonzalo (Ayudante de 2da), Peralta Dalia Soledad (Ayudante de 2da), Polo Tamara Carolina (Ayudante de 2da)
146 | Tipo de clase Día Horario Aula
147 | Práctica Lunes 16:00 a 19:00 Aula a determinar
148 | Práctica Jueves 16:00 a 19:00 Aula a determinar
149 | Subcomisión: Teórica 4
150 | Cupo / insc.: Sin definir / 33
151 | Docentes: Quallbrunn Federico (Ayudante de 1ra)
152 | Tipo de clase Día Horario Aula
153 | Teórico Lunes 17:00 a 19:00 Aula a determinar
154 | Teórico Jueves 17:00 a 19:00 Aula a determinar
155 | Subcomisión: Práctica 4
156 | Cupo / insc.: Sin definir / 33
157 | Docentes: Honore Eduardo Misael (Jefe de TP), Luna Jose Alejandro (Jefe de TP), Belen Eugenia (Ayudante de 2da)
158 | Tipo de clase Día Horario Aula
159 | Práctica Lunes 19:00 a 22:00 Aula a determinar
160 | Práctica Jueves 19:00 a 22:00 Aula a determinar
161 | Actividad: Aprendizaje Automático 2024 (COMP930656)
162 | Comisión: A
163 | Turno: Sin definir
164 | Instancias: Regularidad
165 | Ubicación: Ciudad Universitaria
166 | Subcomisión: AA 1C2024
167 | Cupo / insc.: Sin definir / 58
168 | Docentes: Brusco Pablo (Profesor)
169 | Tipo de clase Día Horario Aula
170 | Teórico-Práctica Martes 17:00 a 21:00 Aula a determinar
171 | Teórico-Práctica Jueves 17:00 a 21:00 Aula a determinar
172 | Actividad: Aprendizaje Automático en Grafos (COMP930663)
173 | Comisión: A
174 | Turno: Sin definir
175 | Instancias: Regularidad
176 | Ubicación: Ciudad Universitaria
177 | Subcomisión: Teórico 1C2024
178 | Cupo / insc.: Sin definir / 29
179 | Docentes: Lombardi Leandro Ezequiel (Profesor)
180 | Tipo de clase Día Horario Aula
181 | Teórico Lunes 09:30 a 12:30 Aula a determinar
182 | Subcomisión: Práctica (virtual) 1C2024
183 | Cupo / insc.: Sin definir / 29
184 | Docentes: Lombardi Leandro Ezequiel (Profesor)
185 | Tipo de clase Día Horario Aula
186 | Práctica Viernes 09:00 a 11:00 Aula a determinar
187 | Actividad: Fundamentos de Artificial General Intelligence Safety (COMP930657)
188 | Comisión: A
189 | Turno: Sin definir
190 | Instancias: Regularidad
191 | Ubicación: Ciudad Universitaria
192 | Subcomisión: FAGIS 1C2024
193 | Cupo / insc.: Sin definir / 38
194 | Docentes: Abriola Sergio Alejandro (Profesor)
195 | Tipo de clase Día Horario Aula
196 | Teórico-Práctica Viernes 17:00 a 21:00 Aula a determinar
197 | Actividad: Introducción a la Programación (COMP230008)
198 | Comisión: A
199 | Turno: Mañana
200 | Instancias: Regularidad
201 | Ubicación: Ciudad Universitaria
202 | Subcomisión: IP Comisión A Laboratorio
203 | Cupo / insc.: Sin definir / 92
204 | Docentes: De Cristoforis Pablo Esteban (Profesor), Di Piazza Gabriela Melisa (Profesor), Godoy Javier Ignacio (Jefe de TP), González Mariano Martín (Jefe de TP), Rubinstein Pablo Andres (Jefe de TP), Sansone Agustín (Ayudante de 1ra), Tilli Dora Elena (Ayudante de 1ra), Bekenstein Jonathan Ezequiel (Ayudante de 2da), Bustamante Luis Ricardo (Ayudante de 2da), Mamani Fernandez Jorge Ricardo (Ayudante de 2da), Perez Bianchi Paula (Ayudante de 2da)
205 | Tipo de clase Día Horario Aula
206 | Laboratorio Lunes 09:00 a 11:30 Aula a determinar
207 | Laboratorio Miércoles 09:00 a 11:30 Aula a determinar
208 | Subcomisión: IP Comisión A Teórico
209 | Cupo / insc.: Sin definir / 92
210 | Docentes: De Cristoforis Pablo Esteban (Profesor), Di Piazza Gabriela Melisa (Profesor), Godoy Javier Ignacio (Jefe de TP), González Mariano Martín (Jefe de TP), Rubinstein Pablo Andres (Jefe de TP), Sansone Agustín (Ayudante de 1ra), Tilli Dora Elena (Ayudante de 1ra), Bekenstein Jonathan Ezequiel (Ayudante de 2da), Bustamante Luis Ricardo (Ayudante de 2da), Mamani Fernandez Jorge Ricardo (Ayudante de 2da), Perez Bianchi Paula (Ayudante de 2da)
211 | Tipo de clase Día Horario Aula
212 | Teórico Jueves 09:00 a 14:00 Aula a determinar
213 | Comisión: B
214 | Turno: Mañana
215 | Instancias: Regularidad
216 | Ubicación: Ciudad Universitaria
217 | Subcomisión: IP Comisión B Laboratorio
218 | Cupo / insc.: Sin definir / 96
219 | Docentes: De Cristoforis Pablo Esteban (Profesor), Di Piazza Gabriela Melisa (Profesor), Godoy Javier Ignacio (Jefe de TP), González Mariano Martín (Jefe de TP), Rubinstein Pablo Andres (Jefe de TP), Sansone Agustín (Ayudante de 1ra), Tilli Dora Elena (Ayudante de 1ra), Bekenstein Jonathan Ezequiel (Ayudante de 2da), Bustamante Luis Ricardo (Ayudante de 2da), Mamani Fernandez Jorge Ricardo (Ayudante de 2da), Perez Bianchi Paula (Ayudante de 2da)
220 | Tipo de clase Día Horario Aula
221 | Laboratorio Lunes 11:30 a 14:00 Aula a determinar
222 | Laboratorio Miércoles 11:30 a 14:00 Aula a determinar
223 | Subcomisión: IP Comisión B Teórico
224 | Cupo / insc.: Sin definir / 96
225 | Docentes: De Cristoforis Pablo Esteban (Profesor), Di Piazza Gabriela Melisa (Profesor), Godoy Javier Ignacio (Jefe de TP), González Mariano Martín (Jefe de TP), Rubinstein Pablo Andres (Jefe de TP), Sansone Agustín (Ayudante de 1ra), Tilli Dora Elena (Ayudante de 1ra), Bekenstein Jonathan Ezequiel (Ayudante de 2da), Bustamante Luis Ricardo (Ayudante de 2da), Mamani Fernandez Jorge Ricardo (Ayudante de 2da), Perez Bianchi Paula (Ayudante de 2da)
226 | Tipo de clase Día Horario Aula
227 | Teórico Jueves 09:00 a 14:00 Aula a determinar
228 | Comisión: C
229 | Turno: Noche
230 | Instancias: Regularidad
231 | Ubicación: Ciudad Universitaria
232 | Subcomisión: IP Comisión C Teórico
233 | Cupo / insc.: Sin definir / 73
234 | Docentes: Altauz Javier Hernán (Profesor), Urtasun Martín (Profesor), Brassesco Maria Virginia (Jefe de TP), Dengra Silvina (Jefe de TP), González Mariano Martín (Jefe de TP), Benedetti Juan Pablo (Ayudante de 1ra), Romano Francisco (Ayudante de 1ra), Vasulka Mariano (Ayudante de 1ra), Vita Sebastian Alberto (Ayudante de 1ra), Lew Deveali Simon (Ayudante de 2da), Ocampo Debora Daiana (Ayudante de 2da)
235 | Tipo de clase Día Horario Aula
236 | Teórico Jueves 17:00 a 22:00 Aula a determinar
237 | Subcomisión: IP Comisión C Laboratorio
238 | Cupo / insc.: Sin definir / 73
239 | Docentes: Altauz Javier Hernán (Profesor), Urtasun Martín (Profesor), Brassesco Maria Virginia (Jefe de TP), Dengra Silvina (Jefe de TP), González Mariano Martín (Jefe de TP), Benedetti Juan Pablo (Ayudante de 1ra), Romano Francisco (Ayudante de 1ra), Vasulka Mariano (Ayudante de 1ra), Vita Sebastian Alberto (Ayudante de 1ra), Lew Deveali Simon (Ayudante de 2da), Ocampo Debora Daiana (Ayudante de 2da)
240 | Tipo de clase Día Horario Aula
241 | Laboratorio Lunes 17:00 a 19:30 Aula a determinar
242 | Laboratorio Miércoles 17:00 a 19:30 Aula a determinar
243 | Comisión: D
244 | Turno: Noche
245 | Instancias: Regularidad
246 | Ubicación: Ciudad Universitaria
247 | Subcomisión: IP Comisión D Laboratorio
248 | Cupo / insc.: Sin definir / 43
249 | Docentes: Altauz Javier Hernán (Profesor), Urtasun Martín (Profesor), Brassesco Maria Virginia (Jefe de TP), Dengra Silvina (Jefe de TP), González Mariano Martín (Jefe de TP), Benedetti Juan Pablo (Ayudante de 1ra), Romano Francisco (Ayudante de 1ra), Vasulka Mariano (Ayudante de 1ra), Vita Sebastian Alberto (Ayudante de 1ra), Lew Deveali Simon (Ayudante de 2da), Ocampo Debora Daiana (Ayudante de 2da)
250 | Tipo de clase Día Horario Aula
251 | Laboratorio Lunes 19:30 a 22:00 Aula a determinar
252 | Laboratorio Miércoles 19:30 a 22:00 Aula a determinar
253 | Subcomisión: IP Comisión D Teórico
254 | Cupo / insc.: Sin definir / 43
255 | Docentes: Altauz Javier Hernán (Profesor), Urtasun Martín (Profesor), Brassesco Maria Virginia (Jefe de TP), Dengra Silvina (Jefe de TP), González Mariano Martín (Jefe de TP), Benedetti Juan Pablo (Ayudante de 1ra), Romano Francisco (Ayudante de 1ra), Vasulka Mariano (Ayudante de 1ra), Vita Sebastian Alberto (Ayudante de 1ra), Lew Deveali Simon (Ayudante de 2da), Ocampo Debora Daiana (Ayudante de 2da)
256 | Tipo de clase Día Horario Aula
257 | Teórico Jueves 17:00 a 22:00 Aula a determinar
258 | Actividad: Modelado y Análisis de Sistemas Reactivos y Concurrentes (COMP931252)
259 | Comisión: A
260 | Turno: Sin definir
261 | Instancias: Regularidad
262 | Ubicación: Ciudad Universitaria
263 | Subcomisión: Laboratorio 1C2024
264 | Cupo / insc.: Sin definir / 1
265 | Docentes: Uchitel Sebastian (Profesor)
266 | Tipo de clase Día Horario Aula
267 | Laboratorio Martes 09:00 a 13:00 Aula a determinar
268 | Subcomisión: Teórico 1C2024
269 | Cupo / insc.: Sin definir / 1
270 | Docentes: Uchitel Sebastian (Profesor)
271 | Tipo de clase Día Horario Aula
272 | Teórico Jueves 10:00 a 12:00 Aula a determinar
273 | Actividad: Modelado y Simulación de Sistemas Complejos con Aplicaciones en Economía (COMP930658)
274 | Comisión: A
275 | Turno: Sin definir
276 | Instancias: Regularidad
277 | Ubicación: Ciudad Universitaria
278 | Observaciones: Materia optativa dictada por les profesores Rodrigo CASTRO, Viktoriya SEMESHENKO, Igal KEJSEFMAN, y Ayelén BARGADOS.
279 | Subcomisión: Teórico 1C2024
280 | Cupo / insc.: Sin definir / 48
281 | Docentes: Castro Rodrigo Daniel (Profesor)
282 | Tipo de clase Día Horario Aula
283 | Teórico Lunes 17:00 a 19:00 Aula a determinar
284 | Subcomisión: Laboratorio 1C2024
285 | Cupo / insc.: Sin definir / 48
286 | Docentes: Castro Rodrigo Daniel (Profesor)
287 | Tipo de clase Día Horario Aula
288 | Laboratorio Lunes 19:00 a 21:00 Aula a determinar
289 | Actividad: Paradigmas de Programación (COMP930015)
290 | Comisión: A
291 | Turno: Sin definir
292 | Instancias: Regularidad
293 | Ubicación: Ciudad Universitaria
294 | Subcomisión: PLP - Teórico-práctica
295 | Cupo / insc.: Sin definir / 285
296 | Docentes: Barenbaum Pablo (Profesor), Cossio Mercado Christian Gustavo (Jefe de TP), Marottoli Daniela (Jefe de TP), Steren Gabriela (Jefe de TP), Díaz Caro Alejandro (Evaluador)
297 | Tipo de clase Día Horario Aula
298 | Teórico-Práctica Martes 17:00 a 22:00 Aula a determinar
299 | Teórico-Práctica Viernes 17:00 a 22:00 Aula a determinar
300 | Subcomisión: PLP - Laboratorio
301 | Cupo / insc.: Sin definir / 285
302 | Docentes: Barenbaum Pablo (Profesor), Cossio Mercado Christian Gustavo (Jefe de TP), Marottoli Daniela (Jefe de TP), Steren Gabriela (Jefe de TP), Díaz Caro Alejandro (Evaluador)
303 | Tipo de clase Día Horario Aula
304 | Laboratorio Martes 17:00 a 22:00 Aula a determinar
305 | Laboratorio Viernes 17:00 a 22:00 Aula a determinar
306 | Actividad: Procesamiento Avanzado de Señales 2024 (COMP930668)
307 | Comisión: A
308 | Turno: Sin definir
309 | Instancias: Regularidad
310 | Ubicación: Ciudad Universitaria
311 | Subcomisión: Teórico 1C2024
312 | Cupo / insc.: Sin definir / 8
313 | Docentes: Risk Marcelo Raul (Profesor)
314 | Tipo de clase Día Horario Aula
315 | Teórico Martes 17:00 a 18:00 Aula a determinar
316 | Subcomisión: Laboratorio 1C2024
317 | Cupo / insc.: Sin definir / 8
318 | Docentes: Risk Marcelo Raul (Profesor)
319 | Tipo de clase Día Horario Aula
320 | Laboratorio Martes 18:00 a 20:00 Aula a determinar
321 | Actividad: Procesamiento de Lenguaje Natural (COMP930662)
322 | Comisión: A
323 | Turno: Sin definir
324 | Instancias: Regularidad
325 | Ubicación: Ciudad Universitaria
326 | Subcomisión: Laboratorio 1C2024
327 | Cupo / insc.: Sin definir / 32
328 | Docentes: Del Corro Luciano Manuel (Profesor)
329 | Tipo de clase Día Horario Aula
330 | Laboratorio Martes 09:00 a 12:00 Aula a determinar
331 | Actividad: Redes, Sociedad y Economía (COMP931538)
332 | Comisión: A
333 | Turno: Sin definir
334 | Instancias: Regularidad
335 | Ubicación: Ciudad Universitaria
336 | Subcomisión: Redes, Sociedad y Economía 1C2023
337 | Cupo / insc.: Sin definir / 19
338 | Docentes: Feuerstein Esteban Zindel (Profesor)
339 | Tipo de clase Día Horario Aula
340 | Teórico-Práctica Martes 17:15 a 21:15 Aula a determinar
341 | Actividad: Seguridad de la Información (COMP931324)
342 | Comisión: A
343 | Turno: Sin definir
344 | Instancias: Regularidad
345 | Ubicación: Ciudad Universitaria
346 | Subcomisión: Teórico-Práctica 1C2024
347 | Cupo / insc.: Sin definir / 23
348 | Docentes: Baader Rodolfo Pablo (Profesor)
349 | Tipo de clase Día Horario Aula
350 | Teórico-Práctica Lunes 18:00 a 20:30 Aula a determinar
351 | Teórico-Práctica Miércoles 18:00 a 20:30 Aula a determinar
352 | Actividad: Sistemas Digitales (COMP230014)
353 | Comisión: Turno Mañana
354 | Turno: Mañana
355 | Instancias: Regularidad
356 | Ubicación: Ciudad Universitaria
357 | Subcomisión: Sistemas Digitales TM Teórico-práctica
358 | Cupo / insc.: Sin definir / 130
359 | Docentes: Buemi María Elena (Profesor), Cerrutti Mariano Javier (Jefe de TP), Bekenstein Jonathan Ezequiel (Ayudante de 2da), Siciliani Andres (Ayudante de 2da), Sánchez Posadas Ramiro (Ayudante de 2da)
360 | Tipo de clase Día Horario Aula
361 | Teórico-Práctica Jueves 08:00 a 10:00 Aula a determinar
362 | Subcomisión: Sistemas Digitales TM Laboratorio
363 | Cupo / insc.: Sin definir / 130
364 | Docentes: Buemi María Elena (Profesor), Cerrutti Mariano Javier (Jefe de TP), Bekenstein Jonathan Ezequiel (Ayudante de 2da), Siciliani Andres (Ayudante de 2da), Sánchez Posadas Ramiro (Ayudante de 2da)
365 | Tipo de clase Día Horario Aula
366 | Laboratorio Jueves 10:00 a 13:00 Aula a determinar
367 | Comisión: Turno Noche
368 | Turno: Noche
369 | Instancias: Regularidad
370 | Ubicación: Ciudad Universitaria
371 | Subcomisión: Sistemas Digitales TN Teórico-práctica
372 | Cupo / insc.: Sin definir / 93
373 | Docentes: Buemi María Elena (Profesor), Zoppi Edgardo Julio (Jefe de TP), Raffo Diego Martín (Ayudante de 1ra), Gonzalez Omahen Augusto Ezequiel (Ayudante de 2da), Romani Rafael (Ayudante de 2da)
374 | Tipo de clase Día Horario Aula
375 | Teórico-Práctica Jueves 17:00 a 19:00 Aula a determinar
376 | Subcomisión: Sistemas Digitales TN Laboratorio
377 | Cupo / insc.: Sin definir / 93
378 | Docentes: Buemi María Elena (Profesor), Zoppi Edgardo Julio (Jefe de TP), Raffo Diego Martín (Ayudante de 1ra), Gonzalez Omahen Augusto Ezequiel (Ayudante de 2da), Romani Rafael (Ayudante de 2da)
379 | Tipo de clase Día Horario Aula
380 | Laboratorio Jueves 19:00 a 22:00 Aula a determinar
381 | Actividad: Sistemas Operativos (COMP930017)
382 | Comisión: A
383 | Turno: Sin definir
384 | Instancias: Regularidad
385 | Ubicación: Ciudad Universitaria
386 | Subcomisión: SO Teórico práctica
387 | Cupo / insc.: Sin definir / 92
388 | Docentes: Fernandez Slezak Diego (Profesor), Sumoza Matos Rodolfo Leonardo (Jefe de TP)
389 | Tipo de clase Día Horario Aula
390 | Teórico-Práctica Martes 17:00 a 21:00 Aula a determinar
391 | Teórico-Práctica Jueves 17:00 a 21:00 Aula a determinar
392 | Subcomisión: SO Laboratorio
393 | Cupo / insc.: Sin definir / 92
394 | Docentes: Fernandez Slezak Diego (Profesor), Sumoza Matos Rodolfo Leonardo (Jefe de TP)
395 | Tipo de clase Día Horario Aula
396 | Laboratorio Martes 17:00 a 21:00 Aula a determinar
397 | Laboratorio Jueves 17:00 a 21:00 Aula a determinar
398 | Actividad: Taller de Tesis I (COMP930660)
399 | Comisión: A
400 | Turno: Sin definir
401 | Instancias: Regularidad
402 | Ubicación: Ciudad Universitaria
403 | Subcomisión: Taller de Tesis I 1ºC2024
404 | Cupo / insc.: Sin definir / 21
405 | Docentes: Kamienkowski Juan Esteban (Profesor)
406 | Tipo de clase Día Horario Aula
407 | Teórico-Práctica Lunes 17:00 a 22:00 Aula a determinar
408 | Actividad: Teoría de Juegos (DC) 2024 (COMP930666)
409 | Comisión: A
410 | Turno: Sin definir
411 | Instancias: Regularidad
412 | Ubicación: Ciudad Universitaria
413 | Subcomisión: Teórico-Práctica 1C2024
414 | Cupo / insc.: Sin definir / 28
415 | Docentes: Arbiser Ariel (Jefe de TP)
416 | Tipo de clase Día Horario Aula
417 | Teórico-Práctica Miércoles 14:30 a 19:00 Aula a determinar
418 | Actividad: Técnicas de Diseño de Algoritmos (COMP230015)
419 | Comisión: A
420 | Turno: Sin definir
421 | Instancias: Regularidad/Promoción
422 | Ubicación: Ciudad Universitaria
423 | Subcomisión: TDA Turno Mañana
424 | Cupo / insc.: 150 / 70
425 | Docentes: Bonomo Flavia (Profesor), Soulignac Francisco Juan (Profesor), Terlisky Pablo Ezequiel (Jefe de TP), Braier Julián (Ayudante de 1ra), Amster Martín (Ayudante de 2da), Umfurer Alfredo Raul (Ayudante de 2da)
426 | Tipo de clase Día Horario Aula
427 | Teórico-Práctica Lunes 09:00 a 13:00 Aula a determinar
428 | Teórico-Práctica Miércoles 09:00 a 13:00 Aula a determinar
429 | Subcomisión: TDA Turno Noche
430 | Cupo / insc.: 150 / 56
431 | Docentes: Lin Min Chih (Profesor), Platzer Emilio (Profesor), Iglesias Matias Nehuen (Jefe de TP), Brandwein Eric (Ayudante de 2da), Companeetz Ezequiel (Ayudante de 2da), Dinkel Ayelen (Ayudante de 2da), Nores Manuel (Ayudante de 2da), Raffo Leandro Javier (Ayudante de 2da), Umfurer Alfredo Raul (Ayudante de 2da)
432 | Tipo de clase Día Horario Aula
433 | Teórico-Práctica Lunes 17:00 a 21:00 Aula a determinar
434 | Teórico-Práctica Miércoles 17:00 a 21:00 Aula a determinar
435 | Actividad: Álgebra I (COMP930001)
436 | Comisión: Algebra I
437 | Turno: Sin definir
438 | Instancias: Regularidad/Promoción
439 | Ubicación: Ciudad Universitaria
440 | Subcomisión: Teórico-práctica 1 (A-K)
441 | Cupo / insc.: Sin definir / 124
442 | Docentes: Zadunaisky Bustillos Pablo Mauricio (Profesor), Merzbacher Diego Mariano (Jefe de TP), Antunes Percincula Carlos Santiago (Ayudante de 1ra), Rufolo Franco Nicolás (Ayudante de 2da)
443 | Tipo de clase Día Horario Aula
444 | Teórico-Práctica Martes 09:00 a 14:00 Aula a determinar
445 | Teórico-Práctica Viernes 09:00 a 14:00 Aula a determinar
446 | Subcomisión: Teórico-práctica 2 (L-Z)
447 | Cupo / insc.: Sin definir / 90
448 | Docentes: Perrucci Daniel Roberto (Profesor), Paredes Marcelo Exequiel (Ayudante de 1ra), Sac Himelfarb Gabriel (Ayudante de 1ra), Fraiman David (Ayudante de 2da)
449 | Tipo de clase Día Horario Aula
450 | Teórico-Práctica Martes 09:00 a 14:00 Aula a determinar
451 | Teórico-Práctica Viernes 09:00 a 14:00 Aula a determinar
452 | Subcomisión: Teórico-práctica 3
453 | Cupo / insc.: Sin definir / 68
454 | Docentes: Krick Teresa Elena Genoveva (Profesor), Freyre Sebastián (Jefe de TP), Giacobbe Mara Georgina (Jefe de TP), Allo Gómez Nicolás (Ayudante de 2da), Lamas Jan (Ayudante de 2da)
455 | Tipo de clase Día Horario Aula
456 | Teórico-Práctica Martes 14:00 a 19:00 Aula a determinar
457 | Teórico-Práctica Viernes 14:00 a 19:00 Aula a determinar
458 | Subcomisión: Teórico-práctica 4
459 | Cupo / insc.: Sin definir / 136
460 | Docentes: Krick Teresa Elena Genoveva (Profesor), Freyre Sebastián (Jefe de TP), Noceti Maria Florencia (Ayudante de 1ra), Martínez Facundo Ezequiel (Ayudante de 2da)
461 | Tipo de clase Día Horario Aula
462 | Teórico-Práctica Martes 17:00 a 22:00 Aula a determinar
463 | Teórico-Práctica Viernes 17:00 a 22:00 Aula a determinar
464 | Actividad: Álgebra Lineal Computacional (LCDA210006)
465 | Comisión: Algebra lineal computacional
466 | Turno: Sin definir
467 | Instancias: Regularidad/Promoción
468 | Ubicación: Ciudad Universitaria
469 | Subcomisión: Teórica
470 | Cupo / insc.: Sin definir / 147
471 | Docentes: Martinez Sandra Rita (Profesor)
472 | Tipo de clase Día Horario Aula
473 | Teórico Martes 09:00 a 11:00 Aula a determinar
474 | Teórico Jueves 09:00 a 11:00 Aula a determinar
475 | Subcomisión: Práctica
476 | Cupo / insc.: Sin definir / 147
477 | Docentes: Statti María Florencia (Jefe de TP), Carabajal Gonzalo (Ayudante de 2da)
478 | Tipo de clase Día Horario Aula
479 | Práctica Martes 11:00 a 14:00 Aula a determinar
480 | Práctica Jueves 11:00 a 14:00 Aula a determinar
481 | Período lectivo: 2024 - 1er. Bimestre
482 | Actividad: Aprendizaje Profundo - VISIT2024 (COMP930671)
483 | Comisión: A
484 | Turno: Sin definir
485 | Instancias: Regularidad
486 | Ubicación: Ciudad Universitaria
487 | Subcomisión: Teórico-Práctica 1B2024
488 | Cupo / insc.: Sin definir / 91
489 | Docentes: Ferrante Enzo (Profesor), Rodriguez Ricardo Oscar (Profesor)
490 | Tipo de clase Día Horario Aula
491 | Teórico-Práctica Martes 09:00 a 12:00 Aula a determinar
492 | Actividad: Criptografía Moderna - VISIT2024 (COMP930669)
493 | Comisión: A
494 | Turno: Sin definir
495 | Instancias: Regularidad
496 | Ubicación: Ciudad Universitaria
497 | Observaciones: Materia optativa dictada por el profesor Fernando Virdia
498 | Subcomisión: Teórico-Práctica 1B2024
499 | Cupo / insc.: Sin definir / 47
500 | Docentes: Rodriguez Ricardo Oscar (Profesor)
501 | Tipo de clase Día Horario Aula
502 | Teórico-Práctica Martes 14:00 a 17:00 Aula a determinar
503 | Teórico-Práctica Jueves 14:00 a 17:00 Aula a determinar
504 | Actividad: Introducción a las APIs - VISIT2024 (COMP930670)
505 | Comisión: A
506 | Turno: Sin definir
507 | Instancias: Regularidad
508 | Ubicación: Ciudad Universitaria
509 | Subcomisión: Teórico-Práctica 1B2024
510 | Cupo / insc.: Sin definir / 127
511 | Docentes: De Caso Guido (Jefe de TP)
512 | Tipo de clase Día Horario Aula
513 | Teórico-Práctica Miércoles 17:00 a 20:00 Aula a determinar
514 | Actividad: Modelado y Análisis de Sistemas Reactivos y Concurrentes (COMP931252)
515 | Comisión: A
516 | Turno: Sin definir
517 | Instancias: Regularidad
518 | Ubicación: Ciudad Universitaria
519 | Subcomisión: Laboratorio 1C2024
520 | Cupo / insc.: Sin definir / 2
521 | Docentes: Uchitel Sebastian (Profesor)
522 | Tipo de clase Día Horario Aula
523 | Laboratorio Martes 09:00 a 13:00 Aula a determinar
524 | Subcomisión: Teórico 1C2024
525 | Cupo / insc.: Sin definir / 2
526 | Docentes: Uchitel Sebastian (Profesor)
527 | Tipo de clase Día Horario Aula
528 | Teórico Jueves 10:00 a 12:00 Aula a determinar
529 | Actividad: Procesamiento de Imágenes Cerebrales a Gran Escala con Aplicaciones de Machine Learning - VISIT2024 (COMP930673)
530 | Comisión: A
531 | Turno: Sin definir
532 | Instancias: Regularidad
533 | Ubicación: Ciudad Universitaria
534 | Observaciones: Materia optativa dictada por el profesor Federico Raimondo.
535 | Subcomisión: Procesamiento de imágenes cerebrales a gran escala con aplicaciones de Machine Learning-1B2024
536 | Cupo / insc.: Sin definir / 45
537 | Docentes: Rodriguez Ricardo Oscar (Profesor)
538 | Tipo de clase Día Horario Aula
539 | Teórico-Práctica Lunes 09:00 a 13:00 Aula a determinar
540 | Teórico-Práctica Martes 09:00 a 13:00 Aula a determinar
541 | Teórico-Práctica Miércoles 09:00 a 13:00 Aula a determinar
542 | Teórico-Práctica Jueves 09:00 a 13:00 Aula a determinar
543 | Teórico-Práctica Viernes 09:00 a 13:00 Aula a determinar
544 | Actividad: Seminario de Demostración Automática 2024 (COMP930664)
545 | Comisión: A
546 | Turno: Sin definir
547 | Instancias: Regularidad
548 | Ubicación: Ciudad Universitaria
549 | Subcomisión: SDA 1C2024
550 | Cupo / insc.: Sin definir / 17
551 | Docentes: Rodriguez Ricardo Oscar (Profesor)
552 | Tipo de clase Día Horario Aula
553 | Teórico-Práctica Miércoles 14:00 a 17:00 Aula a determinar
554 |
555 | `;
556 |
--------------------------------------------------------------------------------
/tests/siu-json/siu-axel.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "periodo": "2024 - 1er Cuatrimestre",
4 | "materias": [
5 | {
6 | "nombre": "ÁLGEBRA LINEAL",
7 | "codigo": "CB002",
8 | "cursos": [
9 | "CB002-CURSO: 01A",
10 | "CB002-CURSO: 01B",
11 | "CB002-CURSO: 02A",
12 | "CB002-CURSO: 02B",
13 | "CB002-CURSO: 03",
14 | "CB002-CURSO: 04A",
15 | "CB002-CURSO: 04B",
16 | "CB002-CURSO: 05",
17 | "CB002-CURSO:06A",
18 | "CB002-CURSO:06B",
19 | "CB002-CURSO:07A",
20 | "CB002-CURSO:07B",
21 | "CB002-CURSO: 13A",
22 | "CB002-CURSO:13B",
23 | "CB002-CURSO:15",
24 | "CB002-CURSO:17",
25 | "CB002-CURSO:19",
26 | "CB002-CURSO:23A",
27 | "CB002-CURSO:23B"
28 | ]
29 | },
30 | {
31 | "nombre": "ALGORITMOS Y ESTRUCTURAS DE DATOS",
32 | "codigo": "CB100",
33 | "cursos": [
34 | "CB100-CURSO: 01-Schmidt A1",
35 | "CB100-CURSO: 02-Buchwald A1",
36 | "CB100-CURSO: 03-Juarez A1",
37 | "CB100-CURSO: 04-Mendez/Pandolfo A1",
38 | "CB100-CURSO: 05-Schmidt A1",
39 | "CB100-CURSO: 01-Schimidt A2",
40 | "CB100-CURSO: 02-Buchwald A2",
41 | "CB100-CURSO: 03-Juarez A2",
42 | "CB100-CURSO: 04-Mendez/Pandolfo A2",
43 | "CB100-CURSO: 05-Schmidt A2"
44 | ]
45 | },
46 | {
47 | "nombre": "ANÁLISIS MATEMÁTICO II",
48 | "codigo": "CB001",
49 | "cursos": [
50 | "CB001-CURSO: 01",
51 | "CB001-CURSO: 02A",
52 | "CB001-CURSO: 02B",
53 | "CB001-CURSO: 03",
54 | "CB001-CURSO: 04A",
55 | "CB001-CURSO: 04B",
56 | "CB001-CURSO: 05A",
57 | "CB001-CURSO: 05B",
58 | "CB001-CURSO: 06A",
59 | "CB001-CURSO: 06B",
60 | "CB001-CURSO: 07",
61 | "CB001-CURSO:11A",
62 | "CB001-CURSO:11B",
63 | "CB001-CURSO:12A",
64 | "CB001-CURSO:12B",
65 | "CB001-CURSO:14",
66 | "CB001-CURSO:10",
67 | "CB001-CURSO:20A",
68 | "CB001-CURSO:20B",
69 | "CB001-CURSO:22",
70 | "CB001-CURSO:23",
71 | "CB001-CURSO: 15",
72 | "CB001-CURSO: 09A",
73 | "CB001-CURSO: 09B"
74 | ]
75 | },
76 | {
77 | "nombre": "ANÁLISIS MATEMÁTICO III",
78 | "codigo": "CB005",
79 | "cursos": ["CB005-CURSO: 02", "CB005-CURSO: 03", "CB005-CURSO: 05"]
80 | },
81 | {
82 | "nombre": "APRENDIZAJE AUTOMÁTICO",
83 | "codigo": "TA061",
84 | "cursos": ["TA061-CURSO: 01-Merlino"]
85 | },
86 | {
87 | "nombre": "BASE DE DATOS",
88 | "codigo": "TA044",
89 | "cursos": ["TA044-CURSO: 01-Román", "TA044-CURSO: 02-Merlino"]
90 | },
91 | {
92 | "nombre": "CIENCIA DE DATOS",
93 | "codigo": "TA047",
94 | "cursos": ["TA047-CURSO: 01-Martinelli", "TA047-CURSO: 02-Rodriguez"]
95 | },
96 | {
97 | "nombre": "COMPUTACIÓN CUÁNTICA",
98 | "codigo": "TB032",
99 | "cursos": ["TB032-CURSO: Caram"]
100 | },
101 | {
102 | "nombre": "EMPRESAS DE BASE TECNOLÓGICA I",
103 | "codigo": "TC018",
104 | "cursos": ["TC018-CURSO: 01-Di Mauro"]
105 | },
106 | {
107 | "nombre": "EMPRESAS DE BASE TECNOLÓGICA II",
108 | "codigo": "TC019",
109 | "cursos": ["TC019-CURSO: 01-Di Mauro"]
110 | },
111 | {
112 | "nombre": "FÍSICA PARA INFORMÁTICA",
113 | "codigo": "CB024",
114 | "cursos": ["CB024-Curso 01"]
115 | },
116 | {
117 | "nombre": "FUNDAMENTOS DE PROGRAMACIÓN",
118 | "codigo": "TB021",
119 | "cursos": [
120 | "TB021-CURSO: 03-Essaya",
121 | "TB021-CURSO: 04-Mendez",
122 | "TB021-CURSO: 01-Guarna",
123 | "TB021-CURSO: 02-Azcurra",
124 | "TB021-CURSO: 05-Mendez"
125 | ]
126 | },
127 | {
128 | "nombre": "GESTIÓN DEL DESARROLLO DE SISTEMAS INFORMÁTICOS",
129 | "codigo": "TC017",
130 | "cursos": ["TC017-CURSO: 01-Fontela"]
131 | },
132 | {
133 | "nombre": "INGENIERÍA DE SOFTWARE I",
134 | "codigo": "TA046",
135 | "cursos": [
136 | "TA046-CURSO:01- Leveroni",
137 | "TA046-CURSO: 02-Villagra",
138 | "TA046-CURSO: 03-Gonzalez"
139 | ]
140 | },
141 | {
142 | "nombre": "INGENIERÍA DE SOFTWARE II",
143 | "codigo": "TA049",
144 | "cursos": ["TA049-CURSO: 01-Montaldo", "TA049-CURSO: 02-Paez"]
145 | },
146 | {
147 | "nombre": "INTRODUCCIÓN AL DESARROLLO DE SOFTWARE",
148 | "codigo": "TB022",
149 | "cursos": ["TB022-CURSO: 03-Camejo", "TB022-CURSO: 05-Lanzillotta"]
150 | },
151 | {
152 | "nombre": "MODELACIÓN NUMÉRICA",
153 | "codigo": "CB051",
154 | "cursos": [
155 | "CB051-CURSO: 01-Re",
156 | "CB051-CURSO: 02-Tarela",
157 | "CB051-CURSO: 03-Griggio",
158 | "CB051-CURSO: 04-Schwarz",
159 | "CB051-CURSO: 05-Sassano",
160 | "CB051-CURSO: 06-Rodriguez",
161 | "CB051-CURSO: 07-Cavaliere Practica Martes 19 hs",
162 | "CB051-CURSO: 08-Cavaliere Práctica Martes 16 hs"
163 | ]
164 | },
165 | {
166 | "nombre": "ORGANIZACIÓN DEL COMPUTADOR",
167 | "codigo": "TB023",
168 | "cursos": [
169 | "TB023-CURSO: 01-Benitez",
170 | "TB023-CURSO: 02-Marchi",
171 | "TB023-CURSO: 03-Burin"
172 | ]
173 | },
174 | {
175 | "nombre": "PARADIGMAS DE PROGRAMACIÓN",
176 | "codigo": "TB025",
177 | "cursos": [
178 | "TB025-CURSO: 01-Suarez",
179 | "TB025-CURSO: 02-Cano",
180 | "TB025-CURSO: 03-Corsi"
181 | ]
182 | },
183 | {
184 | "nombre": "PROBABILIDAD Y ESTADÍSTICA",
185 | "codigo": "CB003",
186 | "cursos": [
187 | "CB003-CURSO: 21",
188 | "CB003-CURSO: 22",
189 | "CB003-CURSO: 25",
190 | "CB003-CURSO: 27",
191 | "CB003-CURSO: 28"
192 | ]
193 | },
194 | {
195 | "nombre": "PROGRAMACIÓN CONCURRENTE",
196 | "codigo": "TB026",
197 | "cursos": ["TB026-CURSO: 01-Deymonnaz"]
198 | },
199 | {
200 | "nombre": "REDES",
201 | "codigo": "TA048",
202 | "cursos": [
203 | "TA048-CURSO:01-ALVAREZ HAMELIN",
204 | "TA048-CURSO: 02-Alvarez Hamelin"
205 | ]
206 | },
207 | {
208 | "nombre": "SIMULACIÓN",
209 | "codigo": "TB028",
210 | "cursos": ["TB028-CURSO: 01-Caiafa"]
211 | },
212 | {
213 | "nombre": "SISTEMAS OPERATIVOS",
214 | "codigo": "TA043",
215 | "cursos": ["TA043-CURSO: 01-Mendez"]
216 | },
217 | {
218 | "nombre": "TALLER DE PROGRAMACIÓN",
219 | "codigo": "TA045",
220 | "cursos": ["TA045-CURSO: 01-Veiga", "TA045-CURSO: 02-Deymonnaz"]
221 | },
222 | {
223 | "nombre": "TEORÍA DE ALGORITMOS",
224 | "codigo": "TB024",
225 | "cursos": ["TB024-CURSO: 01-Podberezski", "TB024-CURSO: 02-Buchwald"]
226 | }
227 | ],
228 | "cursos": [
229 | {
230 | "materia": "CB002",
231 | "codigo": "CB002-CURSO: 01A",
232 | "docentes": "VARGAS GABRIELA , PALACIOS PATRICIA ELIZABE , SOSA MARINA ",
233 | "clases": [
234 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
235 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
236 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
237 | { "dia": 3, "inicio": "11:00", "fin": "13:00" }
238 | ]
239 | },
240 | {
241 | "materia": "CB002",
242 | "codigo": "CB002-CURSO: 01B",
243 | "docentes": "VARGAS GABRIELA , CABANA ADRIANA ELENA , BOHORQUEZ GUTIERREZ RUBEN ANDRES ",
244 | "clases": [
245 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
246 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
247 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
248 | { "dia": 3, "inicio": "11:00", "fin": "13:00" }
249 | ]
250 | },
251 | {
252 | "materia": "CB002",
253 | "codigo": "CB002-CURSO: 02A",
254 | "docentes": "SARRIS CLAUDIA MONICA , PRESENZA JUAN FRANCISCO , ROZENWASSER LAURA ",
255 | "clases": [
256 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
257 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
258 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
259 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
260 | ]
261 | },
262 | {
263 | "materia": "CB002",
264 | "codigo": "CB002-CURSO: 02B",
265 | "docentes": "SARRIS CLAUDIA MONICA , FAGES LUCIANO RODOLFO , VIBRENTIS FRANCISCO ANTONIO ",
266 | "clases": [
267 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
268 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
269 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
270 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
271 | ]
272 | },
273 | {
274 | "materia": "CB002",
275 | "codigo": "CB002-CURSO: 03",
276 | "docentes": "GIRIBET JUAN IGNACIO , PERALTA NORA BEATRIZ , GOMEZ CIAPPONI LAUTARO ",
277 | "clases": [
278 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
279 | { "dia": 3, "inicio": "11:00", "fin": "13:00" },
280 | { "dia": 5, "inicio": "09:00", "fin": "11:00" },
281 | { "dia": 5, "inicio": "11:00", "fin": "13:00" }
282 | ]
283 | },
284 | {
285 | "materia": "CB002",
286 | "codigo": "CB002-CURSO: 04A",
287 | "docentes": "LOPEZ CLAUDIA ANDREA , ORECCHIA MONICA INES , ALVAREZ PONTE LUCIA INES ",
288 | "clases": [
289 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
290 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
291 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
292 | { "dia": 4, "inicio": "11:00", "fin": "13:00" }
293 | ]
294 | },
295 | {
296 | "materia": "CB002",
297 | "codigo": "CB002-CURSO: 04B",
298 | "docentes": "LOPEZ CLAUDIA ANDREA , ROZENWASSER LAURA , KLINGER MAGALI SILVINA ",
299 | "clases": [
300 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
301 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
302 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
303 | { "dia": 4, "inicio": "11:00", "fin": "13:00" }
304 | ]
305 | },
306 | {
307 | "materia": "CB002",
308 | "codigo": "CB002-CURSO: 05",
309 | "docentes": "PALACIOS PATRICIA ELIZABE , VIBRENTIS FRANCISCO ANTONIO , NORES MANUEL ENRIQUE ",
310 | "clases": [
311 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
312 | { "dia": 3, "inicio": "11:00", "fin": "13:00" },
313 | { "dia": 5, "inicio": "09:00", "fin": "11:00" },
314 | { "dia": 5, "inicio": "11:00", "fin": "13:00" }
315 | ]
316 | },
317 | {
318 | "materia": "CB002",
319 | "codigo": "CB002-CURSO:06A",
320 | "docentes": "BOGGI SILVINA , VENTURIELLO VERONICA LAURA ",
321 | "clases": [
322 | { "dia": 1, "inicio": "00:09", "fin": "11:00" },
323 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
324 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
325 | { "dia": 3, "inicio": "11:00", "fin": "13:00" }
326 | ]
327 | },
328 | {
329 | "materia": "CB002",
330 | "codigo": "CB002-CURSO:06B",
331 | "docentes": "BOGGI SILVINA , GARCIA SERRANO SILVINA AIDA , ROHDENBURG ERICA ELISABET ",
332 | "clases": [
333 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
334 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
335 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
336 | { "dia": 3, "inicio": "11:00", "fin": "13:00" }
337 | ]
338 | },
339 | {
340 | "materia": "CB002",
341 | "codigo": "CB002-CURSO:07A",
342 | "docentes": "MARTINS MARCELA , ALVAREZ PONTE LUCIA INES ",
343 | "clases": [
344 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
345 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
346 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
347 | { "dia": 4, "inicio": "11:00", "fin": "13:00" }
348 | ]
349 | },
350 | {
351 | "materia": "CB002",
352 | "codigo": "CB002-CURSO:07B",
353 | "docentes": "MARTINS MARCELA , VALDETTARO MARCELO ALEJAN , ROZENWASSER LAURA ",
354 | "clases": [
355 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
356 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
357 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
358 | { "dia": 4, "inicio": "11:00", "fin": "13:00" }
359 | ]
360 | },
361 | {
362 | "materia": "CB002",
363 | "codigo": "CB002-CURSO: 13A",
364 | "docentes": "CABANA ADRIANA ELENA , PERALTA NORA BEATRIZ , HERRMANN GUILLERMO WALTER ",
365 | "clases": [
366 | { "dia": 3, "inicio": "13:00", "fin": "15:00" },
367 | { "dia": 3, "inicio": "15:00", "fin": "17:00" },
368 | { "dia": 5, "inicio": "13:00", "fin": "15:00" },
369 | { "dia": 5, "inicio": "15:00", "fin": "17:00" }
370 | ]
371 | },
372 | {
373 | "materia": "CB002",
374 | "codigo": "CB002-CURSO:13B",
375 | "docentes": "CABANA ADRIANA ELENA , RODRIGUEZ MARIA LAURA , PONCE DE LEON ROBLES FABIAN ARTURO ",
376 | "clases": [
377 | { "dia": 3, "inicio": "13:00", "fin": "15:00" },
378 | { "dia": 3, "inicio": "15:00", "fin": "17:00" },
379 | { "dia": 5, "inicio": "13:00", "fin": "15:00" },
380 | { "dia": 5, "inicio": "15:00", "fin": "17:00" }
381 | ]
382 | },
383 | {
384 | "materia": "CB002",
385 | "codigo": "CB002-CURSO:15",
386 | "docentes": "ALVAREZ JULIA JORGE , GRÖER MARIA GABRIELA , CATUOGNO EZEQUIEL PATRICIO , AGUERRE JUAN FRANCISCO ",
387 | "clases": [
388 | { "dia": 1, "inicio": "17:00", "fin": "19:00" },
389 | { "dia": 1, "inicio": "19:00", "fin": "21:00" },
390 | { "dia": 3, "inicio": "17:00", "fin": "19:00" },
391 | { "dia": 3, "inicio": "19:00", "fin": "21:00" }
392 | ]
393 | },
394 | {
395 | "materia": "CB002",
396 | "codigo": "CB002-CURSO:17",
397 | "docentes": "MARTINS MARCELA , ORECCHIA MONICA INES , MENDIETA JULIO ANTONIO , CENTENO HERNÁN DIEGO ",
398 | "clases": [
399 | { "dia": 2, "inicio": "07:00", "fin": "09:00" },
400 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
401 | { "dia": 4, "inicio": "07:00", "fin": "09:00" },
402 | { "dia": 4, "inicio": "09:00", "fin": "11:00" }
403 | ]
404 | },
405 | {
406 | "materia": "CB002",
407 | "codigo": "CB002-CURSO:19",
408 | "docentes": "PRELAT DANIEL , GALVAN MONICA BEATRIZ , SILVESTRE DAMIAN ISMAEL ",
409 | "clases": [
410 | { "dia": 1, "inicio": "13:00", "fin": "15:00" },
411 | { "dia": 1, "inicio": "15:00", "fin": "17:00" },
412 | { "dia": 3, "inicio": "13:00", "fin": "15:00" },
413 | { "dia": 3, "inicio": "15:00", "fin": "17:00" }
414 | ]
415 | },
416 | {
417 | "materia": "CB002",
418 | "codigo": "CB002-CURSO:23A",
419 | "docentes": "GRYNBERG SEBASTIAN PABLO , PALAU GABRIEL , CASSANI MARÍA VICTORIA ",
420 | "clases": [
421 | { "dia": 1, "inicio": "07:00", "fin": "09:00" },
422 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
423 | { "dia": 3, "inicio": "07:00", "fin": "09:00" },
424 | { "dia": 3, "inicio": "09:00", "fin": "11:00" }
425 | ]
426 | },
427 | {
428 | "materia": "CB002",
429 | "codigo": "CB002-CURSO:23B",
430 | "docentes": "GRYNBERG SEBASTIAN PABLO , GIACOBBE MARA GEORGINA , PONCE DE LEON ROBLES FABIAN ARTURO ",
431 | "clases": [
432 | { "dia": 1, "inicio": "07:00", "fin": "09:00" },
433 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
434 | { "dia": 3, "inicio": "07:00", "fin": "09:00" },
435 | { "dia": 3, "inicio": "09:00", "fin": "11:00" }
436 | ]
437 | },
438 | {
439 | "materia": "CB100",
440 | "codigo": "CB100-CURSO: 01-Schmidt A1",
441 | "docentes": "SIROTINSKY SERGIO , SCHMIDT GUSTAVO ADOLFO ",
442 | "clases": [
443 | { "dia": 3, "inicio": "19:00", "fin": "22:00" },
444 | { "dia": 5, "inicio": "19:00", "fin": "22:00" }
445 | ]
446 | },
447 | {
448 | "materia": "CB100",
449 | "codigo": "CB100-CURSO: 02-Buchwald A1",
450 | "docentes": "BUCHWALD MARTÍN EZEQUIEL , GENENDER PEÑA EZEQUIEL DAVID , BRASBURG FEDERICO ",
451 | "clases": [
452 | { "dia": 1, "inicio": "17:30", "fin": "20:30" },
453 | { "dia": 4, "inicio": "17:30", "fin": "20:30" }
454 | ]
455 | },
456 | {
457 | "materia": "CB100",
458 | "codigo": "CB100-CURSO: 03-Juarez A1",
459 | "docentes": "JUAREZ ANDRÉS ALBERTO , CIARALLO CRISTIAN ADRIAN , FARETTA YANINA BELEN , MARIANETTI NICOLAS GABRIEL ",
460 | "clases": [
461 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
462 | { "dia": 4, "inicio": "18:00", "fin": "21:00" }
463 | ]
464 | },
465 | {
466 | "materia": "CB100",
467 | "codigo": "CB100-CURSO: 04-Mendez/Pandolfo A1",
468 | "docentes": "MENDEZ MARIANO , SIBIKOWSKI NICOLAS IVAN , CORREA VALENTINA LAURA , DIAZ MIGUEZ ABRIL , PANDOLFO LUCAS HERNAN ",
469 | "clases": [
470 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
471 | { "dia": 4, "inicio": "18:00", "fin": "21:00" }
472 | ]
473 | },
474 | {
475 | "materia": "CB100",
476 | "codigo": "CB100-CURSO: 05-Schmidt A1",
477 | "docentes": "SIROTINSKY SERGIO , SCHMIDT GUSTAVO ADOLFO ",
478 | "clases": [
479 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
480 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
481 | ]
482 | },
483 | {
484 | "materia": "CB100",
485 | "codigo": "CB100-CURSO: 01-Schimidt A2",
486 | "docentes": "SIROTINSKY SERGIO , SCHMIDT GUSTAVO ADOLFO ",
487 | "clases": [
488 | { "dia": 3, "inicio": "19:00", "fin": "22:00" },
489 | { "dia": 5, "inicio": "19:00", "fin": "22:00" }
490 | ]
491 | },
492 | {
493 | "materia": "CB100",
494 | "codigo": "CB100-CURSO: 02-Buchwald A2",
495 | "docentes": "BUCHWALD MARTÍN EZEQUIEL , GENENDER PEÑA EZEQUIEL DAVID , BRASBURG FEDERICO ",
496 | "clases": [
497 | { "dia": 1, "inicio": "17:30", "fin": "20:30" },
498 | { "dia": 4, "inicio": "17:30", "fin": "20:30" }
499 | ]
500 | },
501 | {
502 | "materia": "CB100",
503 | "codigo": "CB100-CURSO: 03-Juarez A2",
504 | "docentes": "JUAREZ ANDRÉS ALBERTO , CIARALLO CRISTIAN ADRIAN , FARETTA YANINA BELEN , MARIANETTI NICOLAS GABRIEL ",
505 | "clases": [
506 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
507 | { "dia": 4, "inicio": "18:00", "fin": "21:00" }
508 | ]
509 | },
510 | {
511 | "materia": "CB100",
512 | "codigo": "CB100-CURSO: 04-Mendez/Pandolfo A2",
513 | "docentes": "MENDEZ MARIANO , SIBIKOWSKI NICOLAS IVAN , DIAZ MIGUEZ ABRIL , PANDOLFO LUCAS HERNAN ",
514 | "clases": [
515 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
516 | { "dia": 4, "inicio": "18:00", "fin": "21:00" }
517 | ]
518 | },
519 | {
520 | "materia": "CB100",
521 | "codigo": "CB100-CURSO: 05-Schmidt A2",
522 | "docentes": "SIROTINSKY SERGIO , SCHMIDT GUSTAVO ADOLFO ",
523 | "clases": [
524 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
525 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
526 | ]
527 | },
528 | {
529 | "materia": "CB001",
530 | "codigo": "CB001-CURSO: 01",
531 | "docentes": "ACERO FERNANDO RODOLFO , PEÑA NELLY HAYDEE , SMILOVICH DAMIAN NICOLAS ",
532 | "clases": [
533 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
534 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
535 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
536 | { "dia": 4, "inicio": "11:00", "fin": "13:00" }
537 | ]
538 | },
539 | {
540 | "materia": "CB001",
541 | "codigo": "CB001-CURSO: 02A",
542 | "docentes": "ACERO FERNANDO RODOLFO , LOPEZ CLAUDIA ANDREA , ENDELLI JORGE RODOLFO ",
543 | "clases": [
544 | { "dia": 2, "inicio": "07:00", "fin": "09:00" },
545 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
546 | { "dia": 4, "inicio": "07:00", "fin": "09:00" },
547 | { "dia": 4, "inicio": "09:00", "fin": "11:00" }
548 | ]
549 | },
550 | {
551 | "materia": "CB001",
552 | "codigo": "CB001-CURSO: 02B",
553 | "docentes": "ACERO FERNANDO RODOLFO , GARCIA ADRIANA EVA , PORTOCARRERO MIRANDA MICHAEL ",
554 | "clases": [
555 | { "dia": 2, "inicio": "07:00", "fin": "09:00" },
556 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
557 | { "dia": 4, "inicio": "07:00", "fin": "09:00" },
558 | { "dia": 4, "inicio": "09:00", "fin": "11:00" }
559 | ]
560 | },
561 | {
562 | "materia": "CB001",
563 | "codigo": "CB001-CURSO: 03",
564 | "docentes": "GIGOLA SILVIA VIVIANA , DE ROSSI FERNANDO DANIEL , OLIVA CARLA MARIANA ",
565 | "clases": [
566 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
567 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
568 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
569 | { "dia": 3, "inicio": "11:00", "fin": "13:00" }
570 | ]
571 | },
572 | {
573 | "materia": "CB001",
574 | "codigo": "CB001-CURSO: 04A",
575 | "docentes": "ZITTO MIGUEL EDUARDO , GOMEZ CIAPPONI LAUTARO , BIBILONI FERNANDO ",
576 | "clases": [
577 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
578 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
579 | { "dia": 5, "inicio": "09:00", "fin": "11:00" },
580 | { "dia": 5, "inicio": "11:00", "fin": "13:00" }
581 | ]
582 | },
583 | {
584 | "materia": "CB001",
585 | "codigo": "CB001-CURSO: 04B",
586 | "docentes": "ZITTO MIGUEL EDUARDO , DURANTE FLAVIO ANIBAL , LA COLLA AUGUSTO ",
587 | "clases": [
588 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
589 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
590 | { "dia": 5, "inicio": "09:00", "fin": "11:00" },
591 | { "dia": 5, "inicio": "11:00", "fin": "13:00" }
592 | ]
593 | },
594 | {
595 | "materia": "CB001",
596 | "codigo": "CB001-CURSO: 05A",
597 | "docentes": "MAULHARDT MARTIN ENRIQUE , PUEBLA MANUEL LEANDRO , RIZZO ELISABETH AMALIA , BLAZQUEZ ROCIO AZUL ",
598 | "clases": [
599 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
600 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
601 | { "dia": 5, "inicio": "09:00", "fin": "11:00" },
602 | { "dia": 5, "inicio": "11:00", "fin": "13:00" }
603 | ]
604 | },
605 | {
606 | "materia": "CB001",
607 | "codigo": "CB001-CURSO: 05B",
608 | "docentes": "MAULHARDT MARTIN ENRIQUE , MONZON NELSON , BIBILONI FERNANDO ",
609 | "clases": [
610 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
611 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
612 | { "dia": 5, "inicio": "09:00", "fin": "11:00" },
613 | { "dia": 5, "inicio": "11:00", "fin": "13:00" }
614 | ]
615 | },
616 | {
617 | "materia": "CB001",
618 | "codigo": "CB001-CURSO: 06A",
619 | "docentes": "SOLA MARCOS OSCAR , PIÑERA EDUARDO ERNESTO ",
620 | "clases": [
621 | { "dia": 1, "inicio": "13:00", "fin": "15:00" },
622 | { "dia": 1, "inicio": "15:00", "fin": "17:00" },
623 | { "dia": 3, "inicio": "13:00", "fin": "15:00" },
624 | { "dia": 3, "inicio": "15:00", "fin": "17:00" }
625 | ]
626 | },
627 | {
628 | "materia": "CB001",
629 | "codigo": "CB001-CURSO: 06B",
630 | "docentes": "SOLA MARCOS OSCAR , GUALTIERI SERGIO ALBERTO , OLIVA CARLA MARIANA ",
631 | "clases": [
632 | { "dia": 1, "inicio": "13:00", "fin": "15:00" },
633 | { "dia": 1, "inicio": "15:00", "fin": "17:00" },
634 | { "dia": 3, "inicio": "13:00", "fin": "15:00" },
635 | { "dia": 3, "inicio": "15:00", "fin": "17:00" }
636 | ]
637 | },
638 | {
639 | "materia": "CB001",
640 | "codigo": "CB001-CURSO: 07",
641 | "docentes": "A DESIGNAR A DESIGNAR , ENDELLI JORGE RODOLFO , KLINGER MAGALI SILVINA , PUEBLA MANUEL LEANDRO ",
642 | "clases": [
643 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
644 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
645 | { "dia": 4, "inicio": "09:00", "fin": "11:00" },
646 | { "dia": 4, "inicio": "11:00", "fin": "13:00" }
647 | ]
648 | },
649 | {
650 | "materia": "CB001",
651 | "codigo": "CB001-CURSO:11A",
652 | "docentes": "MARTINS MARCELA , ROSSI PABLO DANIEL , ZHANG FAN ",
653 | "clases": [
654 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
655 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
656 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
657 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
658 | ]
659 | },
660 | {
661 | "materia": "CB001",
662 | "codigo": "CB001-CURSO:11B",
663 | "docentes": "DE ROSSI FERNANDO DANIEL , HERRMANN GUILLERMO WALTER ",
664 | "clases": [
665 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
666 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
667 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
668 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
669 | ]
670 | },
671 | {
672 | "materia": "CB001",
673 | "codigo": "CB001-CURSO:12A",
674 | "docentes": "LOPEZ CLAUDIA ANDREA , SILVESTRE DAMIAN ISMAEL , VOROBIOFF NICOLAS ",
675 | "clases": [
676 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
677 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
678 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
679 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
680 | ]
681 | },
682 | {
683 | "materia": "CB001",
684 | "codigo": "CB001-CURSO:12B",
685 | "docentes": "LOPEZ CLAUDIA ANDREA , VICEDO JUAN PABLO , ZHANG FAN ",
686 | "clases": [
687 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
688 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
689 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
690 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
691 | ]
692 | },
693 | {
694 | "materia": "CB001",
695 | "codigo": "CB001-CURSO:14",
696 | "docentes": "COMAS JORGE MIGUEL , CANEPA VICTOR MANUEL , MEDINA MANUELA ",
697 | "clases": [
698 | { "dia": 2, "inicio": "18:00", "fin": "20:00" },
699 | { "dia": 2, "inicio": "20:00", "fin": "22:00" },
700 | { "dia": 5, "inicio": "18:00", "fin": "20:00" },
701 | { "dia": 5, "inicio": "20:00", "fin": "22:00" }
702 | ]
703 | },
704 | {
705 | "materia": "CB001",
706 | "codigo": "CB001-CURSO:10",
707 | "docentes": "SASYK ROMAN , CHORNY FERNANDO , GUALTIERI SERGIO ALBERTO ",
708 | "clases": [
709 | { "dia": 1, "inicio": "13:00", "fin": "15:00" },
710 | { "dia": 1, "inicio": "15:00", "fin": "17:00" },
711 | { "dia": 3, "inicio": "13:00", "fin": "15:00" },
712 | { "dia": 3, "inicio": "15:00", "fin": "17:00" }
713 | ]
714 | },
715 | {
716 | "materia": "CB001",
717 | "codigo": "CB001-CURSO:20A",
718 | "docentes": "SEMINARA SILVIA ALEJANDRA , OLIVA CECILIA MARIEL , LUCUY SUAREZ FRED ALBERTO ",
719 | "clases": [
720 | { "dia": 1, "inicio": "17:00", "fin": "19:00" },
721 | { "dia": 1, "inicio": "19:00", "fin": "21:00" },
722 | { "dia": 3, "inicio": "17:00", "fin": "19:00" },
723 | { "dia": 3, "inicio": "19:00", "fin": "21:00" }
724 | ]
725 | },
726 | {
727 | "materia": "CB001",
728 | "codigo": "CB001-CURSO:20B",
729 | "docentes": "SEMINARA SILVIA ALEJANDRA , ESTRIN ANDRES ALEJANDRO , WILK BERNARDO ",
730 | "clases": [
731 | { "dia": 1, "inicio": "17:00", "fin": "19:00" },
732 | { "dia": 1, "inicio": "19:00", "fin": "21:00" },
733 | { "dia": 3, "inicio": "17:00", "fin": "19:00" },
734 | { "dia": 3, "inicio": "19:00", "fin": "21:00" }
735 | ]
736 | },
737 | {
738 | "materia": "CB001",
739 | "codigo": "CB001-CURSO:22",
740 | "docentes": "MANCILLA AGUILAR JOSE LUIS , CENTENO HERNÁN DIEGO , A DESIGNAR A DESIGNAR ",
741 | "clases": [
742 | { "dia": 2, "inicio": "00:09", "fin": "11:00" },
743 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
744 | { "dia": 4, "inicio": "00:09", "fin": "11:00" },
745 | { "dia": 4, "inicio": "11:00", "fin": "13:00" }
746 | ]
747 | },
748 | {
749 | "materia": "CB001",
750 | "codigo": "CB001-CURSO:23",
751 | "docentes": "A DESIGNAR A DESIGNAR , AMOREO ANIBAL , PETROVICH JOSE LUIS ALEJANDRO ",
752 | "clases": [
753 | { "dia": 2, "inicio": "18:00", "fin": "20:00" },
754 | { "dia": 2, "inicio": "20:00", "fin": "22:00" },
755 | { "dia": 4, "inicio": "18:00", "fin": "20:00" },
756 | { "dia": 4, "inicio": "20:00", "fin": "22:00" }
757 | ]
758 | },
759 | {
760 | "materia": "CB001",
761 | "codigo": "CB001-CURSO: 15",
762 | "docentes": "SASSANO MIRYAM PATRICIA , RAMOS GALKER ELIANA MAITE , VENTURIELLO VERONICA LAURA ",
763 | "clases": [
764 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
765 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
766 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
767 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
768 | ]
769 | },
770 | {
771 | "materia": "CB001",
772 | "codigo": "CB001-CURSO: 09A",
773 | "docentes": "PASTOR VERONICA ESTELA , ROHDENBURG ERICA ELISABET , VENTURIELLO VERONICA LAURA ",
774 | "clases": [
775 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
776 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
777 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
778 | { "dia": 3, "inicio": "11:00", "fin": "13:00" }
779 | ]
780 | },
781 | {
782 | "materia": "CB001",
783 | "codigo": "CB001-CURSO: 09B",
784 | "docentes": "PASTOR VERONICA ESTELA , BUCELLO PABLO AUGUSTO , SOSA MARINA ",
785 | "clases": [
786 | { "dia": 1, "inicio": "09:00", "fin": "11:00" },
787 | { "dia": 1, "inicio": "11:00", "fin": "13:00" },
788 | { "dia": 3, "inicio": "09:00", "fin": "11:00" },
789 | { "dia": 3, "inicio": "11:00", "fin": "13:00" }
790 | ]
791 | },
792 | {
793 | "materia": "CB005",
794 | "codigo": "CB005-CURSO: 02",
795 | "docentes": "PRELAT DANIEL , DE ROSSI FERNANDO DANIEL ",
796 | "clases": [
797 | { "dia": 2, "inicio": "09:00", "fin": "11:00" },
798 | { "dia": 2, "inicio": "11:00", "fin": "13:00" },
799 | { "dia": 5, "inicio": "09:00", "fin": "11:00" },
800 | { "dia": 5, "inicio": "11:00", "fin": "13:00" }
801 | ]
802 | },
803 | {
804 | "materia": "CB005",
805 | "codigo": "CB005-CURSO: 03",
806 | "docentes": "MURMIS GUSTAVO MARCELO , BURMAN ARIEL , DEL RIO GARCIA FEDERICO MANUEL ",
807 | "clases": [
808 | { "dia": 1, "inicio": "18:00", "fin": "20:00" },
809 | { "dia": 1, "inicio": "20:00", "fin": "22:00" },
810 | { "dia": 3, "inicio": "18:00", "fin": "20:00" },
811 | { "dia": 3, "inicio": "20:00", "fin": "22:00" }
812 | ]
813 | },
814 | {
815 | "materia": "CB005",
816 | "codigo": "CB005-CURSO: 05",
817 | "docentes": "CACHILE MARIO ANDRES , PEÑA NELLY HAYDEE , A DESIGNAR A DESIGNAR , GOMEZ CIAPPONI LAUTARO , MONZON NELSON ",
818 | "clases": [
819 | { "dia": 2, "inicio": "14:00", "fin": "16:00" },
820 | { "dia": 2, "inicio": "16:00", "fin": "18:00" },
821 | { "dia": 4, "inicio": "14:00", "fin": "16:00" },
822 | { "dia": 4, "inicio": "16:00", "fin": "18:00" }
823 | ]
824 | },
825 | {
826 | "materia": "TA061",
827 | "codigo": "TA061-CURSO: 01-Merlino",
828 | "docentes": "IERACHE JORGE SALVADOR , MERLINO HERNAN DANIEL ",
829 | "clases": [
830 | { "dia": 2, "inicio": "07:00", "fin": "10:00" },
831 | { "dia": 4, "inicio": "07:00", "fin": "10:00" }
832 | ]
833 | },
834 | {
835 | "materia": "TA044",
836 | "codigo": "TA044-CURSO: 01-Román",
837 | "docentes": "FASCE ALBERTO ARMANDO , ROMAN LUCAS ALEJANDRO ",
838 | "clases": [
839 | { "dia": 2, "inicio": "19:00", "fin": "22:00" },
840 | { "dia": 3, "inicio": "19:00", "fin": "22:00" }
841 | ]
842 | },
843 | {
844 | "materia": "TA044",
845 | "codigo": "TA044-CURSO: 02-Merlino",
846 | "docentes": "MERLINO HERNAN DANIEL ",
847 | "clases": [
848 | { "dia": 1, "inicio": "07:00", "fin": "09:00" },
849 | { "dia": 3, "inicio": "07:00", "fin": "09:00" },
850 | { "dia": 5, "inicio": "07:00", "fin": "09:00" }
851 | ]
852 | },
853 | {
854 | "materia": "TA047",
855 | "codigo": "TA047-CURSO: 01-Martinelli",
856 | "docentes": "MARTINELLI DAMIAN ARIEL , GOLMAR NATALIA ",
857 | "clases": [
858 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
859 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
860 | ]
861 | },
862 | {
863 | "materia": "TA047",
864 | "codigo": "TA047-CURSO: 02-Rodriguez",
865 | "docentes": "RODRIGUEZ JUAN MANUEL , VILLANUEVA CECILIA AZUL ",
866 | "clases": [
867 | { "dia": 2, "inicio": "19:00", "fin": "22:00" },
868 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
869 | ]
870 | },
871 | {
872 | "materia": "TB032",
873 | "codigo": "TB032-CURSO: Caram",
874 | "docentes": "CARAM LEONIDAS FACUNDO , SARRIS CLAUDIA MONICA ",
875 | "clases": [
876 | { "dia": 3, "inicio": "19:00", "fin": "22:00" },
877 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
878 | ]
879 | },
880 | {
881 | "materia": "TC018",
882 | "codigo": "TC018-CURSO: 01-Di Mauro",
883 | "docentes": "GODOY ANDRES ALEJANDRO ",
884 | "clases": [
885 | { "dia": 1, "inicio": "18:00", "fin": "21:00" },
886 | { "dia": 5, "inicio": "18:00", "fin": "21:00" }
887 | ]
888 | },
889 | {
890 | "materia": "TC019",
891 | "codigo": "TC019-CURSO: 01-Di Mauro",
892 | "docentes": "Sin docentes",
893 | "clases": [
894 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
895 | { "dia": 4, "inicio": "18:00", "fin": "21:00" }
896 | ]
897 | },
898 | {
899 | "materia": "CB024",
900 | "codigo": "CB024-Curso 01",
901 | "docentes": "MATTEO CLAUDIA LEDA ",
902 | "clases": [{ "dia": 3, "inicio": "14:00", "fin": "18:00" }]
903 | },
904 | {
905 | "materia": "TB021",
906 | "codigo": "TB021-CURSO: 03-Essaya",
907 | "docentes": "ESSAYA DIEGO NICOLAS , BRASBURG FEDERICO , ESTEBAN FEDERICO MARTÍN , DI SANTO JAVIER MARIANO , KRISTAL JUAN IGNACIO , SANTONI MAURO JAVIER , SPORTELLI CASTRO LUCIANO ",
908 | "clases": [
909 | { "dia": 1, "inicio": "17:30", "fin": "20:30" },
910 | { "dia": 5, "inicio": "17:30", "fin": "20:30" }
911 | ]
912 | },
913 | {
914 | "materia": "TB021",
915 | "codigo": "TB021-CURSO: 04-Mendez",
916 | "docentes": "MENDEZ MARIANO , FRACCARO AGUSTINA , RODRIGUEZ DALA TOMAS ",
917 | "clases": [
918 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
919 | { "dia": 4, "inicio": "18:00", "fin": "21:00" }
920 | ]
921 | },
922 | {
923 | "materia": "TB021",
924 | "codigo": "TB021-CURSO: 01-Guarna",
925 | "docentes": "GUARNA PABLO FRANCISCO ",
926 | "clases": [
927 | { "dia": 2, "inicio": "19:00", "fin": "22:00" },
928 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
929 | ]
930 | },
931 | {
932 | "materia": "TB021",
933 | "codigo": "TB021-CURSO: 02-Azcurra",
934 | "docentes": "AZCURRA DIEGO ANDRES , SALVIA MARTIN MIGUEL , BIANCHI GUSTAVO OSCAR , OTERO MARCOS JULIAN ",
935 | "clases": [{ "dia": 3, "inicio": "16:00", "fin": "22:00" }]
936 | },
937 | {
938 | "materia": "TB021",
939 | "codigo": "TB021-CURSO: 05-Mendez",
940 | "docentes": "MENDEZ MARIANO , LOPEZ JUAN JOSE , MARTOS PEDRO IGNACIO DOMINGO ",
941 | "clases": [
942 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
943 | { "dia": 3, "inicio": "17:00", "fin": "20:00" }
944 | ]
945 | },
946 | {
947 | "materia": "TC017",
948 | "codigo": "TC017-CURSO: 01-Fontela",
949 | "docentes": "FONTELA MOISES CARLOS ",
950 | "clases": [{ "dia": 3, "inicio": "16:00", "fin": "22:00" }]
951 | },
952 | {
953 | "materia": "TA046",
954 | "codigo": "TA046-CURSO:01- Leveroni",
955 | "docentes": "LEVERONI LUCIANO , BURELLA JUAN MATIAS ",
956 | "clases": [
957 | { "dia": 2, "inicio": "18:00", "fin": "22:00" },
958 | { "dia": 5, "inicio": "17:00", "fin": "21:00" }
959 | ]
960 | },
961 | {
962 | "materia": "TA046",
963 | "codigo": "TA046-CURSO: 02-Villagra",
964 | "docentes": "VILLAGRA SERGIO GUSTAVO ",
965 | "clases": [
966 | { "dia": 1, "inicio": "18:30", "fin": "21:30" },
967 | { "dia": 4, "inicio": "18:30", "fin": "21:30" }
968 | ]
969 | },
970 | {
971 | "materia": "TA046",
972 | "codigo": "TA046-CURSO: 03-Gonzalez",
973 | "docentes": "GONZALEZ NORBERTO DANIEL , TURRI ALEJANDRO ",
974 | "clases": [
975 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
976 | { "dia": 3, "inicio": "19:00", "fin": "22:00" }
977 | ]
978 | },
979 | {
980 | "materia": "TA049",
981 | "codigo": "TA049-CURSO: 01-Montaldo",
982 | "docentes": "MONTALDO DIEGO FERNANDO , CUROTTO CARLOS EZEQUIEL , CARAMÉS AGUSTÍN EDUARDO ",
983 | "clases": [
984 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
985 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
986 | ]
987 | },
988 | {
989 | "materia": "TA049",
990 | "codigo": "TA049-CURSO: 02-Paez",
991 | "docentes": "PAEZ NICOLAS MARTIN , de la FUENTE HERNAN ",
992 | "clases": [
993 | { "dia": 1, "inicio": "08:00", "fin": "11:00" },
994 | { "dia": 4, "inicio": "08:00", "fin": "11:00" }
995 | ]
996 | },
997 | {
998 | "materia": "TB022",
999 | "codigo": "TB022-CURSO: 03-Camejo",
1000 | "docentes": "CAMEJO MANUEL , BILBAO MANUEL IÑAKI , DIAZ REAL MARIA SOL , RIEDEL NICOLAS AGUSTIN ",
1001 | "clases": [
1002 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
1003 | { "dia": 5, "inicio": "19:00", "fin": "22:00" }
1004 | ]
1005 | },
1006 | {
1007 | "materia": "TB022",
1008 | "codigo": "TB022-CURSO: 05-Lanzillotta",
1009 | "docentes": "LANZILLOTTA BRUNO , CAPRA FRANCO DANIEL , SOSA CRISTIAN MARTIN ",
1010 | "clases": [
1011 | { "dia": 2, "inicio": "18:00", "fin": "21:00" },
1012 | { "dia": 4, "inicio": "18:00", "fin": "21:00" }
1013 | ]
1014 | },
1015 | {
1016 | "materia": "CB051",
1017 | "codigo": "CB051-CURSO: 01-Re",
1018 | "docentes": "RE MARIANO , GARCIA PABLO EZEQUIEL , SARTI MARINA ",
1019 | "clases": [
1020 | { "dia": 2, "inicio": "16:00", "fin": "19:00" },
1021 | { "dia": 4, "inicio": "16:00", "fin": "19:00" }
1022 | ]
1023 | },
1024 | {
1025 | "materia": "CB051",
1026 | "codigo": "CB051-CURSO: 02-Tarela",
1027 | "docentes": "TARELA PABLO ADRIAN , EZCURRA DIEGO MARTIN , POLTARAK GUILLERMO RAUL CARLOS , DIAZ MARIA BELEN ",
1028 | "clases": [
1029 | { "dia": 1, "inicio": "18:00", "fin": "21:00" },
1030 | { "dia": 3, "inicio": "19:00", "fin": "22:00" }
1031 | ]
1032 | },
1033 | {
1034 | "materia": "CB051",
1035 | "codigo": "CB051-CURSO: 03-Griggio",
1036 | "docentes": "GRIGGIO DANIEL ADALBERTO , NAVARRO FABIAN , CERRUTTI SILVANA VALERIA ",
1037 | "clases": [
1038 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
1039 | { "dia": 3, "inicio": "18:00", "fin": "22:00" }
1040 | ]
1041 | },
1042 | {
1043 | "materia": "CB051",
1044 | "codigo": "CB051-CURSO: 04-Schwarz",
1045 | "docentes": "SCHWARZ RODOLFO ALEJANDRO , SOSA GERMAN EZEQUIEL , CASTAÑO ENRIQUETA ",
1046 | "clases": [
1047 | { "dia": 1, "inicio": "16:00", "fin": "19:00" },
1048 | { "dia": 5, "inicio": "16:00", "fin": "19:00" }
1049 | ]
1050 | },
1051 | {
1052 | "materia": "CB051",
1053 | "codigo": "CB051-CURSO: 05-Sassano",
1054 | "docentes": "SASSANO MIRYAM PATRICIA , GARCIA EZEQUIEL , HUSAIN CERRUTI IGNACIO SANTIAGO , TURANO MARIA AGUSTINA ",
1055 | "clases": [
1056 | { "dia": 3, "inicio": "16:00", "fin": "19:00" },
1057 | { "dia": 4, "inicio": "16:00", "fin": "19:00" }
1058 | ]
1059 | },
1060 | {
1061 | "materia": "CB051",
1062 | "codigo": "CB051-CURSO: 06-Rodriguez",
1063 | "docentes": "RODRIGUEZ DANIEL FABIAN , MACHIUNAS VALERIA ",
1064 | "clases": [
1065 | { "dia": 3, "inicio": "16:00", "fin": "19:00" },
1066 | { "dia": 5, "inicio": "16:00", "fin": "19:00" }
1067 | ]
1068 | },
1069 | {
1070 | "materia": "CB051",
1071 | "codigo": "CB051-CURSO: 07-Cavaliere Practica Martes 19 hs",
1072 | "docentes": "CAVALIERE MIGUEL ANGEL , MASTROPIETRO GABRIEL MARCELO , EZCURRA DIEGO MARTIN , KOWAL ADRIAN MARCELO ",
1073 | "clases": [
1074 | { "dia": 2, "inicio": "19:00", "fin": "22:00" },
1075 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
1076 | ]
1077 | },
1078 | {
1079 | "materia": "CB051",
1080 | "codigo": "CB051-CURSO: 08-Cavaliere Práctica Martes 16 hs",
1081 | "docentes": "CAVALIERE MIGUEL ANGEL , BALZAROTTI FEDERICO , GARCIA PABLO EZEQUIEL , PORTOCARRERO MIRANDA MICHAEL ",
1082 | "clases": [
1083 | { "dia": 2, "inicio": "16:00", "fin": "19:00" },
1084 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
1085 | ]
1086 | },
1087 | {
1088 | "materia": "TB023",
1089 | "codigo": "TB023-CURSO: 01-Benitez",
1090 | "docentes": "BENITEZ CARLOS EDUARDO , MANSILLA MARIANO CLAUDIO , BERRUEZO RAMIRO NICOLÁS , MARTOS PEDRO IGNACIO DOMINGO , RADUCCI DARIO MARTIN ",
1091 | "clases": [
1092 | { "dia": 2, "inicio": "19:00", "fin": "23:00" },
1093 | { "dia": 3, "inicio": "19:00", "fin": "23:00" }
1094 | ]
1095 | },
1096 | {
1097 | "materia": "TB023",
1098 | "codigo": "TB023-CURSO: 02-Marchi",
1099 | "docentes": "MARCHI EDGARDO JOSE , CERVETTO MARCOS ADRIAN ",
1100 | "clases": [
1101 | { "dia": 1, "inicio": "18:00", "fin": "22:00" },
1102 | { "dia": 3, "inicio": "18:00", "fin": "22:00" }
1103 | ]
1104 | },
1105 | {
1106 | "materia": "TB023",
1107 | "codigo": "TB023-CURSO: 03-Burin",
1108 | "docentes": "BURIN ABRAHAM ALBERTO DA , NOVODVORETZ OSCAR DARIO , GUTIERREZ NESTOR SERGIO ",
1109 | "clases": [
1110 | { "dia": 1, "inicio": "15:00", "fin": "19:00" },
1111 | { "dia": 2, "inicio": "19:00", "fin": "23:00" }
1112 | ]
1113 | },
1114 | {
1115 | "materia": "TB025",
1116 | "codigo": "TB025-CURSO: 01-Suarez",
1117 | "docentes": "SANCHEZ DIEGO , SUAREZ JOSE PABLO , NAFTALI MAIA RAQUEL , RODRIGUEZ MASSUH PABLO MATIAS ",
1118 | "clases": [
1119 | { "dia": 2, "inicio": "19:00", "fin": "22:00" },
1120 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
1121 | ]
1122 | },
1123 | {
1124 | "materia": "TB025",
1125 | "codigo": "TB025-CURSO: 02-Cano",
1126 | "docentes": "BRASBURG FEDERICO , CANO MATÍAS JOSÉ , RAIK IGNACIO MARTIN ",
1127 | "clases": [
1128 | { "dia": 3, "inicio": "18:30", "fin": "21:30" },
1129 | { "dia": 5, "inicio": "17:30", "fin": "20:30" }
1130 | ]
1131 | },
1132 | {
1133 | "materia": "TB025",
1134 | "codigo": "TB025-CURSO: 03-Corsi",
1135 | "docentes": "CORSI DIEGO PABLO , ESSAYA DIEGO NICOLAS ",
1136 | "clases": [
1137 | { "dia": 1, "inicio": "14:00", "fin": "17:00" },
1138 | { "dia": 4, "inicio": "14:00", "fin": "17:00" }
1139 | ]
1140 | },
1141 | {
1142 | "materia": "CB003",
1143 | "codigo": "CB003-CURSO: 21",
1144 | "docentes": "VERA MATÍAS ALEJANDRO , PUEBLA MANUEL LEANDRO , MENDAÑA JOAQUÍN ",
1145 | "clases": [
1146 | { "dia": 1, "inicio": "15:00", "fin": "17:00" },
1147 | { "dia": 3, "inicio": "15:00", "fin": "19:00" }
1148 | ]
1149 | },
1150 | {
1151 | "materia": "CB003",
1152 | "codigo": "CB003-CURSO: 22",
1153 | "docentes": "BELLO IGNACIO ALBERTO , LEVITÁN DAVID ADRIÁN , BERTALOT FEDERICO MATIAS ",
1154 | "clases": [
1155 | { "dia": 1, "inicio": "19:00", "fin": "21:00" },
1156 | { "dia": 3, "inicio": "19:00", "fin": "23:00" }
1157 | ]
1158 | },
1159 | {
1160 | "materia": "CB003",
1161 | "codigo": "CB003-CURSO: 25",
1162 | "docentes": "COSATTO AMMANN PEDRO CAMILO , SOSA MARINA , EDWARDS MOLINA DIEGO JULIO ",
1163 | "clases": [
1164 | { "dia": 3, "inicio": "09:00", "fin": "13:00" },
1165 | { "dia": 5, "inicio": "09:00", "fin": "11:00" }
1166 | ]
1167 | },
1168 | {
1169 | "materia": "CB003",
1170 | "codigo": "CB003-CURSO: 27",
1171 | "docentes": "PÉREZ SILVIA NOEMÍ , ALVAREZ PONTE LUCIA INES , DE ANGELIS RIVA LUKAS NAHUEL ",
1172 | "clases": [
1173 | { "dia": 1, "inicio": "09:00", "fin": "13:00" },
1174 | { "dia": 3, "inicio": "09:00", "fin": "11:00" }
1175 | ]
1176 | },
1177 | {
1178 | "materia": "CB003",
1179 | "codigo": "CB003-CURSO: 28",
1180 | "docentes": "KORNBLIT FERNANDO , MENDIBURU MARIANA , ROBLES EZEQUIEL MILAGROS DE JESUS ",
1181 | "clases": [
1182 | { "dia": 3, "inicio": "17:00", "fin": "19:00" },
1183 | { "dia": 5, "inicio": "17:00", "fin": "21:00" }
1184 | ]
1185 | },
1186 | {
1187 | "materia": "TB026",
1188 | "codigo": "TB026-CURSO: 01-Deymonnaz",
1189 | "docentes": "DEYMONNAZ PABLO ANDRES , SCARPINELLI ARIEL ALEJANDRO ",
1190 | "clases": [
1191 | { "dia": 2, "inicio": "19:00", "fin": "22:00" },
1192 | { "dia": 3, "inicio": "19:00", "fin": "22:00" }
1193 | ]
1194 | },
1195 | {
1196 | "materia": "TA048",
1197 | "codigo": "TA048-CURSO:01-ALVAREZ HAMELIN",
1198 | "docentes": "ALVAREZ HAMELIN JOSE IGNACIO ",
1199 | "clases": [
1200 | { "dia": 2, "inicio": "19:00", "fin": "22:00" },
1201 | { "dia": 5, "inicio": "19:00", "fin": "22:00" }
1202 | ]
1203 | },
1204 | {
1205 | "materia": "TA048",
1206 | "codigo": "TA048-CURSO: 02-Alvarez Hamelin",
1207 | "docentes": "ALVAREZ HAMELIN JOSE IGNACIO ",
1208 | "clases": [
1209 | { "dia": 4, "inicio": "18:00", "fin": "21:00" },
1210 | { "dia": 5, "inicio": "19:00", "fin": "22:00" }
1211 | ]
1212 | },
1213 | {
1214 | "materia": "TB028",
1215 | "codigo": "TB028-CURSO: 01-Caiafa",
1216 | "docentes": "CAIAFA CESAR FEDERICO , BENITEZ CARLOS MARCELO , VILLANUEVA CECILIA AZUL ",
1217 | "clases": [
1218 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
1219 | { "dia": 5, "inicio": "19:00", "fin": "22:00" }
1220 | ]
1221 | },
1222 | {
1223 | "materia": "TA043",
1224 | "codigo": "TA043-CURSO: 01-Mendez",
1225 | "docentes": "MENDEZ MARIANO , MUCCIO ADRIAN , ESPINA EMMANUEL EDUARDO , IRIBARNE CATELLA PATRICIO ",
1226 | "clases": [
1227 | { "dia": 3, "inicio": "18:00", "fin": "21:00" },
1228 | { "dia": 5, "inicio": "19:00", "fin": "22:00" }
1229 | ]
1230 | },
1231 | {
1232 | "materia": "TA045",
1233 | "codigo": "TA045-CURSO: 01-Veiga",
1234 | "docentes": "VEIGA ANDRES ARTURO , DI PAOLA MARTIN PABLO , GOMEZ PETER FEDERICO MANUEL , WERNER EZEQUIEL MAXIMILIANO ",
1235 | "clases": [
1236 | { "dia": 2, "inicio": "18:00", "fin": "22:00" },
1237 | { "dia": 4, "inicio": "18:00", "fin": "22:00" }
1238 | ]
1239 | },
1240 | {
1241 | "materia": "TA045",
1242 | "codigo": "TA045-CURSO: 02-Deymonnaz",
1243 | "docentes": "DEYMONNAZ PABLO ANDRES , MILETTA CARLOS MARTIN , TOSCANO GONNELLA MAURO FABRICIO ",
1244 | "clases": [
1245 | { "dia": 1, "inicio": "18:00", "fin": "22:00" },
1246 | { "dia": 4, "inicio": "18:00", "fin": "22:00" }
1247 | ]
1248 | },
1249 | {
1250 | "materia": "TB024",
1251 | "codigo": "TB024-CURSO: 01-Podberezski",
1252 | "docentes": "PODBEREZSKI VICTOR DANIEL ",
1253 | "clases": [
1254 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
1255 | { "dia": 3, "inicio": "19:00", "fin": "22:00" }
1256 | ]
1257 | },
1258 | {
1259 | "materia": "TB024",
1260 | "codigo": "TB024-CURSO: 02-Buchwald",
1261 | "docentes": "BUCHWALD MARTÍN EZEQUIEL , GENENDER PEÑA EZEQUIEL DAVID ",
1262 | "clases": [
1263 | { "dia": 1, "inicio": "19:00", "fin": "22:00" },
1264 | { "dia": 4, "inicio": "19:00", "fin": "22:00" }
1265 | ]
1266 | }
1267 | ],
1268 | "timestamp": 1710968529311
1269 | }
1270 | ]
1271 |
--------------------------------------------------------------------------------