From 07d11f371f107aa17c0caeb1e066f8cf4890e812 Mon Sep 17 00:00:00 2001 From: Raul Date: Fri, 23 Jun 2023 17:35:26 +0200 Subject: [PATCH 01/14] Trying to improve. Adding interpolation demos --- next.config.js | 1 + package.json | 6 +- pages/demos/bezier/index.tsx | 189 ++++++++++++++++++++++++ pages/index.tsx | 21 ++- src/components/LinkIcon.tsx | 18 +++ src/components/SectionItemReference.tsx | 34 +++++ yarn.lock | 20 +++ 7 files changed, 284 insertions(+), 5 deletions(-) create mode 100644 pages/demos/bezier/index.tsx create mode 100644 src/components/LinkIcon.tsx create mode 100644 src/components/SectionItemReference.tsx diff --git a/next.config.js b/next.config.js index fca7f65..3d8eaa8 100644 --- a/next.config.js +++ b/next.config.js @@ -6,6 +6,7 @@ module.exports = { '/articles': { page: '/articles' }, '/projects': { page: '/projects' }, '/books': { page: '/books' }, + '/demos/bezier': { page: '/demos/bezier' }, }; }, async redirects() { diff --git a/package.json b/package.json index 5fe1600..b6bf7b0 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "@material-ui/lab": "^4.0.0-alpha.56", "next": "12.2.5", "react": "18.2.0", - "react-dom": "18.2.0" + "react-dom": "18.2.0", + "rulyotano.math.geometry": "0.1.0", + "rulyotano.math.interpolation.bezier": "0.1.0" }, "devDependencies": { "@babel/preset-env": "^7.18.10", @@ -27,4 +29,4 @@ "react-test-renderer": "^18.2.0", "typescript": "^4.8.2" } -} \ No newline at end of file +} diff --git a/pages/demos/bezier/index.tsx b/pages/demos/bezier/index.tsx new file mode 100644 index 0000000..59090bc --- /dev/null +++ b/pages/demos/bezier/index.tsx @@ -0,0 +1,189 @@ +import { useState, useRef, MouseEvent } from "react"; +import { makeStyles } from '@material-ui/core/styles'; +import Button from '@material-ui/core/Button'; +import Container from '@material-ui/core/Container'; +import Input from '@material-ui/core/Input'; +import AppBar from "components/Appbar"; +import Head from 'next/head'; +import { Point } from "rulyotano.math.geometry"; +import { BezierInterpolation } from "rulyotano.math.interpolation.bezier"; + +export default function App() { + const classes = useStyles(); + const [smooth, setSmooth] = useState(0.8); + const canvasRef = useRef(null); + const [isClosed, setIsClosed] = useState(false); + const [dragginIndex, setDraggingIndex] = useState(null); + const initialPoints = [ + new Point(60, 60), + new Point(7, 9), + new Point(20, 50), + new Point(90, 90), + new Point(190, 40) + ]; + const [points, setPoints] = useState(initialPoints); + const path = BezierInterpolation.bezierToPath( + BezierInterpolation.pointsToBezierCurves(points, isClosed, smooth) + ); + + const onSmoothChange = (newSmoothValue: number) => { + setSmooth(newSmoothValue); + }; + + const onIsClosedChange = (newIsClosed: boolean) => { + setIsClosed(newIsClosed); + }; + + const getPointFromMouseEventCoordinates = (x: number, y: number) => { + const canvas = canvasRef.current; + const boundingClient = canvas?.getBoundingClientRect(); + return new Point(x - boundingClient!.left, y - boundingClient!.top); + }; + + const onAddPoint = (x: number, y: number) => { + setPoints([...points, getPointFromMouseEventCoordinates(x, y)]); + }; + + const onClear = () => { + setPoints(initialPoints); + }; + + const onPointDragStart = (pointIndex: number) => { + if (dragginIndex !== null) return; + setDraggingIndex(pointIndex); + }; + + const onMouseMove = (e: MouseEvent) => { + if (e.buttons === 1 && dragginIndex !== null) { + setPoints([ + ...points.slice(0, dragginIndex), + getPointFromMouseEventCoordinates(e.clientX, e.clientY), + ...points.slice(dragginIndex + 1) + ]); + } + }; + + const onMouseUp = (e: MouseEvent) => { + if (dragginIndex !== null) { + setDraggingIndex(null); + } else { + onAddPoint(e.clientX, e.clientY); + } + }; + + const onPointMouseUp = (e: MouseEvent, pointIndex: number) => { + if (dragginIndex === null) { + setPoints([ + ...points.slice(0, pointIndex), + ...points.slice(pointIndex + 1) + ]); + e.stopPropagation(); + } + }; + + return ( +
+ + Demo interpolate with Bezier curves + + + +

Demo interpolate with Bezier curves

+ + onMouseUp(e)} + onMouseMove={(e) => onMouseMove(e)} + > + + {points.map((p, i) => ( + + ))} + + +

Click in the background to add new point

+

Click in one point to delete it

+

Drag & Drop the points

+ + onSmoothChange(Number.parseFloat(e.target.value))} + /> +
+ {" "} + onIsClosedChange(e.target.checked) + }} + /> +
+ +
+
+ ); +} + +function CanvasPoint({ + point, + index, + onDragStart, + onPointMouseUp +}: { + point: Point; + index: number; + onDragStart: (i: number) => void; + onPointMouseUp: (e: MouseEvent, i: number) => void; +}) { + const classes = useStyles(); + return ( + { + if (e.buttons === 1) { + onDragStart(index); + } + }} + onMouseUp={(e) => onPointMouseUp(e, index)} + /> + ); +} + +const useStyles = makeStyles((theme) => ({ + canvas: { + backgroundColor: theme.palette.background.paper, + width: "100%", + height: "400px", + }, + path: { + fill: "none", + stroke: theme.palette.info.main + }, + point: { + '&:hover': { + strokeWidth: theme.spacing(0.3) + } + } +})) \ No newline at end of file diff --git a/pages/index.tsx b/pages/index.tsx index 1c02540..cafdc85 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { makeStyles } from '@material-ui/core/styles'; import MailIcon from "@material-ui/icons/Mail"; import GitHubIcon from "@material-ui/icons/GitHub"; import LocationOnIcon from "@material-ui/icons/LocationOn"; @@ -9,7 +10,6 @@ import Typography from "@material-ui/core/Typography"; import Chip from "@material-ui/core/Chip"; import Box from "@material-ui/core/Box"; import Grid from "@material-ui/core/Grid"; -// import Skeleton from '@material-ui/lab/Skeleton'; import Copyright from "components/Copyright"; import Avatar from "components/Avatar"; import ReferenceIcon from "components/ReferenceIcon"; @@ -18,7 +18,7 @@ import StackOverflowItem from "components/StackOverflowItem"; import StackOverflowIcon from "components/icons/StackOverflowIcon"; import HackerrankIcon from "components/icons/HackerrankIcon"; import CodesignalIcon from "components/icons/CodesignalIcon"; -import AppBar from "components/Appbar"; +import SectionItemReference from "components/SectionItemReference"; import DataItem from "components/DataItem"; import settings from "data.json"; import gravatar from "gravatar.json"; @@ -29,9 +29,9 @@ export default function Index() { const [gravatarItem] = gravatar.entry; const profileImage = `${gravatarItem.thumbnailUrl}?s=160`; + const classes = useStyles(); return (
- @@ -137,6 +137,15 @@ export default function Index() { + + + + + + + + + {settings.techStaff.map(staff => ( @@ -153,3 +162,9 @@ export default function Index() {
); } + +const useStyles = makeStyles((theme) => ({ + title: { + marginLeft: theme.spacing(2) + } +})) \ No newline at end of file diff --git a/src/components/LinkIcon.tsx b/src/components/LinkIcon.tsx new file mode 100644 index 0000000..941de9d --- /dev/null +++ b/src/components/LinkIcon.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import IconButton from '@material-ui/core/IconButton'; +import Launch from '@material-ui/icons/Launch'; + +export default function ExpandButton({ }) { + const classes = useStyles(); + + return ( + + + + ); +} + +const useStyles = makeStyles((theme) => ({ + +})) diff --git a/src/components/SectionItemReference.tsx b/src/components/SectionItemReference.tsx new file mode 100644 index 0000000..122ef9e --- /dev/null +++ b/src/components/SectionItemReference.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import Box from '@material-ui/core/Box'; +import Divider from '@material-ui/core/Divider'; +import Typography from '@material-ui/core/Typography'; +// import Link from '@material-ui/core/Link'; +import LinkIcon from './LinkIcon'; +import Link from './Link'; + +export default function SectionItem({ title = "", link = "" }) { + const classes = useStyles(); + + return ( + + + + {title} + + + + + + + ); +} + +const useStyles = makeStyles((theme) => ({ + title: { + marginLeft: theme.spacing(2) + }, + link: { + width: '100%' + } +})) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 2d15bfc..2851687 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4554,6 +4554,26 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +rulyotano.math.geometry@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/rulyotano.math.geometry/-/rulyotano.math.geometry-0.1.0.tgz#a9d8b706bec59d870a8f34ea94cb4872def2c4da" + integrity sha512-sKAF9GaWVDMGuJ+At9JQRyxgkHlWo9ULx3cefLnCHfpwWtZlqq0dIEO2FrCNZ3V8IijloqgkYOK6rHd4v3NiuQ== + dependencies: + rulyotano.math "0.9.0" + +rulyotano.math.interpolation.bezier@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/rulyotano.math.interpolation.bezier/-/rulyotano.math.interpolation.bezier-0.1.0.tgz#15bccbfc4db26ecc2d1c492734fcee81a3ce059c" + integrity sha512-yr4oGs9kK3eZzkSUO8/yinoj0OllUi0emGsJhCQlUpLi/LCT1ZnVrfGAmzm5Ekx4VDgxVSP3wER+iCVBmxu4oA== + dependencies: + rulyotano.math "0.9.0" + rulyotano.math.geometry "0.1.0" + +rulyotano.math@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/rulyotano.math/-/rulyotano.math-0.9.0.tgz#1591fa6072890db3710b55132c7a839bf48bbed2" + integrity sha512-eKGqVGg8cDmJoAR0JKGzM6l7UN8M4vrtARoKWQMMiGrVCNzK9O9a6RzJ8pP7pj1zvZG1PJudHvnOS/orj7H+Dw== + safe-buffer@^5.0.1, safe-buffer@^5.1.2: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" From ab7fb0041a826fe98ed9cabc5bbc0a7f2854a2b4 Mon Sep 17 00:00:00 2001 From: Raul Date: Fri, 23 Jun 2023 17:50:21 +0200 Subject: [PATCH 02/14] Fix compilation errors --- pages/demos/bezier/index.tsx | 9 +++------ src/components/SectionItemReference.tsx | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/pages/demos/bezier/index.tsx b/pages/demos/bezier/index.tsx index 59090bc..c95864e 100644 --- a/pages/demos/bezier/index.tsx +++ b/pages/demos/bezier/index.tsx @@ -125,13 +125,10 @@ export default function App() { />
{" "} - onIsClosedChange(e.target.checked) - }} + checked={isClosed} + onChange={(e) => onIsClosedChange(e.target.checked)} />
diff --git a/src/components/SectionItemReference.tsx b/src/components/SectionItemReference.tsx index 122ef9e..fe6f276 100644 --- a/src/components/SectionItemReference.tsx +++ b/src/components/SectionItemReference.tsx @@ -3,15 +3,15 @@ import { makeStyles } from '@material-ui/core/styles'; import Box from '@material-ui/core/Box'; import Divider from '@material-ui/core/Divider'; import Typography from '@material-ui/core/Typography'; -// import Link from '@material-ui/core/Link'; +import Link from '@material-ui/core/Link'; import LinkIcon from './LinkIcon'; -import Link from './Link'; +// import Link from './Link'; export default function SectionItem({ title = "", link = "" }) { const classes = useStyles(); return ( - + {title} From 36072f163c9cd0e1b39bd39987b77a2e6910e2ec Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 4 Jul 2023 11:48:10 +0200 Subject: [PATCH 03/14] Fix link --- src/components/Link.tsx | 4 +++- src/components/SectionItemReference.tsx | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Link.tsx b/src/components/Link.tsx index 2dfd5fd..691ee9c 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -59,10 +59,12 @@ interface LinkProps { onClick?: Function, prefetch?: boolean, innerRef?: Ref, + children?: React.ReactNode, + color?: string } interface Href { pathname: string } -export default React.forwardRef((props, ref) => ); +export default React.forwardRef((props, ref) => ); diff --git a/src/components/SectionItemReference.tsx b/src/components/SectionItemReference.tsx index fe6f276..7475bd7 100644 --- a/src/components/SectionItemReference.tsx +++ b/src/components/SectionItemReference.tsx @@ -3,9 +3,9 @@ import { makeStyles } from '@material-ui/core/styles'; import Box from '@material-ui/core/Box'; import Divider from '@material-ui/core/Divider'; import Typography from '@material-ui/core/Typography'; -import Link from '@material-ui/core/Link'; +// import Link from '@material-ui/core/Link'; import LinkIcon from './LinkIcon'; -// import Link from './Link'; +import Link from './Link'; export default function SectionItem({ title = "", link = "" }) { const classes = useStyles(); From 3c9b236f16e45c52a624eedc7fb6bbdba3f709ce Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 4 Jul 2023 12:02:46 +0200 Subject: [PATCH 04/14] added medium link --- pages/index.tsx | 8 ++++++++ src/components/icons/MediumIcon.tsx | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/components/icons/MediumIcon.tsx diff --git a/pages/index.tsx b/pages/index.tsx index cafdc85..afe8b2a 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -18,6 +18,7 @@ import StackOverflowItem from "components/StackOverflowItem"; import StackOverflowIcon from "components/icons/StackOverflowIcon"; import HackerrankIcon from "components/icons/HackerrankIcon"; import CodesignalIcon from "components/icons/CodesignalIcon"; +import MediumIcon from "components/icons/MediumIcon"; import SectionItemReference from "components/SectionItemReference"; import DataItem from "components/DataItem"; import settings from "data.json"; @@ -95,6 +96,13 @@ export default function Index() { href="https://app.codesignal.com/profile/rulyotano" /> + + + + + + + + ); +} From 53635c48471b80e19eba68d3f28f0325195444ed Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 4 Jul 2023 15:26:22 +0200 Subject: [PATCH 05/14] Improved the bezier demo --- pages/demos/bezier/index.tsx | 181 +++++++++++++++++++++++------------ src/components/Link.tsx | 3 +- 2 files changed, 124 insertions(+), 60 deletions(-) diff --git a/pages/demos/bezier/index.tsx b/pages/demos/bezier/index.tsx index c95864e..c5ca7e6 100644 --- a/pages/demos/bezier/index.tsx +++ b/pages/demos/bezier/index.tsx @@ -2,11 +2,20 @@ import { useState, useRef, MouseEvent } from "react"; import { makeStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; import Container from '@material-ui/core/Container'; -import Input from '@material-ui/core/Input'; +import Box from '@material-ui/core/Box'; import AppBar from "components/Appbar"; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; +import TextField from '@material-ui/core/TextField'; +import Checkbox from '@material-ui/core/Checkbox'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; import Head from 'next/head'; import { Point } from "rulyotano.math.geometry"; import { BezierInterpolation } from "rulyotano.math.interpolation.bezier"; +import { Helpers } from "rulyotano.math.geometry"; +import Typography from "@material-ui/core/Typography"; +import Link from "components/Link"; export default function App() { const classes = useStyles(); @@ -41,7 +50,12 @@ export default function App() { }; const onAddPoint = (x: number, y: number) => { - setPoints([...points, getPointFromMouseEventCoordinates(x, y)]); + const newPoint = getPointFromMouseEventCoordinates(x, y); + const bestIndexToInsert = Helpers.bestPlaceToInsertPoint(newPoint, points); + + setPoints([...points.slice(0, bestIndexToInsert), + newPoint, + ...points.slice(bestIndexToInsert)]); }; const onClear = () => { @@ -88,73 +102,125 @@ export default function App() { -

Demo interpolate with Bezier curves

- - onMouseUp(e)} - onMouseMove={(e) => onMouseMove(e)} - > - - {points.map((p, i) => ( - + + + Demo interpolate with Bezier curves + + + + + + This is to demonstrate how we can use the rulyotano.math.interpolation.bezier library to draw a curve that pass through a set of ordered points. + + + You can find this demo's code base in here. + + + + + + Feel free to play a bit with the points. You can: + + + + + - ))} - - -

Click in the background to add new point

-

Click in one point to delete it

-

Drag & Drop the points

- - onSmoothChange(Number.parseFloat(e.target.value))} - /> -
- {" "} - onIsClosedChange(e.target.checked)} - /> -
- + + + + + + + + + + + + + + + + + + + onMouseUp(e)} + onMouseMove={(e) => onMouseMove(e)} + > + + {points.map((p, i) => ( + + ))} + + + + + onSmoothChange(Number.parseFloat(e.target.value))} + /> + + onIsClosedChange(e.target.checked)} />} label="Is Close Curve" /> + + +
); } +type PointProps = { + point: Point; + index: number; + onDragStart: (i: number) => void; + onPointMouseUp: (e: MouseEvent, i: number) => void; +}; + function CanvasPoint({ point, index, onDragStart, onPointMouseUp -}: { - point: Point; - index: number; - onDragStart: (i: number) => void; - onPointMouseUp: (e: MouseEvent, i: number) => void; -}) { - const classes = useStyles(); +}: PointProps) { + const [isMouseIn, setIsMouseIn] = useState(false); return ( setIsMouseIn(true)} + onMouseLeave={() => setIsMouseIn(false)} onMouseUp={(e) => onPointMouseUp(e, index)} /> ); @@ -177,10 +245,5 @@ const useStyles = makeStyles((theme) => ({ path: { fill: "none", stroke: theme.palette.info.main - }, - point: { - '&:hover': { - strokeWidth: theme.spacing(0.3) - } } })) \ No newline at end of file diff --git a/src/components/Link.tsx b/src/components/Link.tsx index 691ee9c..77f204a 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -60,7 +60,8 @@ interface LinkProps { prefetch?: boolean, innerRef?: Ref, children?: React.ReactNode, - color?: string + color?: string, + target?: string } interface Href { From 3faefb6ac13ede02e9cae96e5180764731b17b61 Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 5 Jul 2023 11:53:56 +0200 Subject: [PATCH 06/14] More tunning. Update experience. Added summary. Updated projects --- pages/index.tsx | 36 ++++++++++++++++++++++++++++++--- public/img/demo-bezier.jpg | Bin 0 -> 29976 bytes public/img/mimacom-favicon.ico | Bin 0 -> 38078 bytes src/data.json | 28 +++++++++++++++++-------- 4 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 public/img/demo-bezier.jpg create mode 100644 public/img/mimacom-favicon.ico diff --git a/pages/index.tsx b/pages/index.tsx index afe8b2a..4797f49 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -114,6 +114,36 @@ export default function Index() { + + I am a passionate coder with expertise in web development and a strong focus on clean code, good practices, and solid principles. I have a deep love for coding, algorithms, and data structures, and I enjoy working with various web technologies. + + + I have a solid understanding of system design and architecture, enabling me to create scalable and efficient solutions. I am also enthusiastic about contributing to open-source libraries and helpers. + + + Let's collaborate and build amazing software together! + + + Highlighted used Tech: + + + ReactJS + AngularJS + Vue + JavaScript + TypeScript + .NET + C# + Python + TypeScript + Node.js + Docker + Docker Swarm + GitHub Actions + K8s + + + {settings.experience.map(it => ( - + - + - + diff --git a/public/img/demo-bezier.jpg b/public/img/demo-bezier.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9f4efadcc1ae32168262983064e1c3cc68242e40 GIT binary patch literal 29976 zcmeEu2RxkXy6=cc7a@ccCecd}LWnkLdYI@fOcI@_A%ZYckcbjJy6AnhQAU{{I?;*V z+vwf&`&nnNeUi1;UVEQ?*8Sac@7?%jzIT}M*5~>E|IhQj1B;ML7@!1qJ94 z@C_mlgYJST4;?!A0lp3cKUBx4s16^dI&t*qkz=P$oH}*##L1J?r|Hg6pQb&1^5mIw zXK2sTGcYimqG4n@N6$n@&p?0hArzFrdk#|_r=mJePkoY_{=fW1{sN*sMzKSgPD#NE zIz&rBNlQWg3Ic;b6jVTM4=VhZFN#Az9giG6cKpOi;17^zK!+$ODGwc{Jg7DB*B-#{ zL5FFn=&lIeK5|y=@ljR>df`{WpO3NKDX3vk?^1V1@e}75na*F};N;@w;S~|R zAtruP;_f|JIe7&|B@In2Z5>@bePa_-Gjj_|t7lHm&s|=)y1jYp?c@9IyN+pCf_E&ENoXn}SeI((S&@X>>IQ5@@Wip}#5s16Nsf(!rv1{gf39J#|D~4wwPF9+t|8DVN(x}` zC}}|u(EbTOzR%s29K`g;3>`z2xmfJW%IU*_<-3We-Tamylaypo`WoR488oOy1|0(v zA@CV6sm1H21YZsr^p=K{fZn7bgG}WKm*Lw)GUy{5&kLGa$SWe9f#5vJpe6`09K8OD z4C>h<-6n&UGblroP#ycX$e=|$8FZNp+SP>D9wmdI<5=LaF!8kNzyImKyZ7G{>EBD{ z-^StpOWUg>o%J1V25YrJw+{xzFnzlv4Y>fyl%;<_VdOmt!-9s$pfBj{>qhQB6>nYW zRg(qL|37>&%vbXQ?saE?0QkvU3=3L6mFX!$|BGFu!)Id_tiSl`=^E<>O>~gMGj{dE z&NT1ee+8w0AQA3lF#A$OIH!SY@P`mJgDUzp_>7DlcThkYk8Kspl zOMz?>6L*r|g4BZ~KW@+;U#-4h&$M-x20NA%DbC71@0#LzIstkXODE0_dQo$efiCv3 zDVKGeh<)G23CHB498|7)Vy2_RrgQB|+(|ieC%BWm{>NWi;|%a7w zH6L^j;?6pP;AI1!fZ@&~q<<_WQd|ACiP<=6)acR;hh|cC+bJ?=HPB%DNOAg6ZHKf{ z+i}-8CBHBZwdHWq6pYprL*$3gchh^3L6t{fWDpC#o-_Y!tC3;5JsISwV|fvyYQ>A% z(&BA#7_5?(@I3tBO}f&xh(+tAUSQn5i~tXyzkeZ}v<$?}duJ%BJG@`%nuxT=pvN8~v4#y0Fdd&KS-SPOq&*(LK@bLmU0y?NTQ#~c}C zp12nO<|DF4FgK~N2=7QO(V{T(%J^+gUF)N+Opoui;YNPPhoraiR=clX7cw&rX>(NE zNy*tb5y7hV@;$d?Bg$i~j|@_3^o030m=-VH@iwa}b~QIoN!kmjaM~WNDAIGzSgTf1 zAGM_?gId4x(wXixG1(=1KFP*NXnfCk#+F+jTfUihHrY6XZC}^rDE67A)ox_g#d9xG zp)%iWIlW?Sncqo&dJgGftzgp^B@V3_g&fK4*9_@8W;{zSvV zkolQ3D|!)uowl0rc=(PC3QcG!Tv8Vtd0{n)_M4hL14sEO)3o<&=2Z%W-z0;=#kNWk z0s`-A7h@q&shibk?=}>7Qu*opKQ<%Wpj<<1BHdUk^pdL(wlD~1F(E{Vd_9RS8 z*GBrNvRYDn#9f{ZnxVd%VI=d}!@&_)3YHh{NDDvnTMk-XP%<=G+0;ijhD}GV@ij=Z zBDUNF>ps2qagL$h*; z_dM)*Ze*&&r-46pmka{y2ZWbqy+4%;IF35cw4kDeb>h-+W=D!PCL0^sv1ka^%BbcO z)DFcX;9ur(ePZjQIL?7_Yfnx?hRpee=I(De*mIODI5Gkr2e$3@RT0o2?TnK_#`5{T z`UPZAGa7qlcWY4zh7}}(*iF0i6KuQji;kX*@?_BafVe13zWAh?up6d$)H#8 z1+&WCpNd|h8Goq^pN2Z|TTn_JaVBJfsJBZ7ao3ynr@uqHxSwK9Eb)Ofwo;)trmXWK zE96ot20d2EAiQO>&RDLhbRKEej#$>3V6kaaP#xaXs*wccjA#%6h|hDAY*j57*-0O7Nc5u1B1)(U8KYQ?zDQy z%%rx^9F%jNjnDkWOMoH2DL-oW8K3@r9%J^Py5mes|+s@2Yki8PtKI z5r)@4^9Dxpj7N4zeu#6gNcmN#W)aQ;c|}fb*%5#5`wD9Bc@?R@$tbsK$ao+N9>h0gm~tz;wDY-~{D&C%%LbGt8fb>%O@JFIh5 zxCRc}fcL(6VB+RdT{7~;bc8zsQ`qIvdbi$(C0wj6qG}AW z=5{bT^S6Fua419=BhR5R<{@C*+$=oY2v|!o8n)~e)_`mS6QJnA=Os1#zz%)Vpe zcH^-Gy_Mv*5`2GM;>=Tw$kc@z4Ca9x0sMaU)PZPr5Z z?)S)`&UZN|zKWr)$a>YW08*(Gjj29_S{av$)9nTN!ukQ^xwt7Al&3?B-ZWMO-dl|r zzK?PsgYHk6k?s_6C&y3|LI7F<^a1OovV{2{(jhVk%eoxRnM^aDkAm)feoW*ojwq7f zn+k@Esq<`%Kdjpm;DGKu^eX_r6ICG1rM^g5{Wgv3A^}q<%A39fpECZXhV3H6uC?B*j$htSx|b6)`q3}5F06t^fR?Q{Zr zWWZiXI~g=y@D@75GH6o{@DjTL=W*Z1 z8a&ij6bSzC{vbiwP?C{gqRcuwAQ|4(m&r@05l6?Nw^QCMQNOeg!2$qP@o8%k5>j-P zoea{-uB{$8)0BWaW(ApKiHGhmo^yfhe4C{pgQ|7k;M8{XJ0^9uElDcA{TYb&!+oOI z6w@x9JSTp+c9(Wz`}f4H^TXKfEYY`%-(rfVdbY&86*P6;h8o?LrPnrlb-;-J=rVGj zLSShO;a}j}0J;3JbnCnbKqVO#j2HmVNsSktC^TsAJ z=pB;`#>1KwVX@b2>ZJWhzuR;({q`u0!|G`!_g99R?0JhS_(B3$esgJNu+>PQC5N#J zT<;8%iMOP;$iCqHVX-u1xctDe3p4Bi%x+5J zAA`KAl*Ps8-R+W0%PS4oPtG!a=oO&}Pp-sVo}O?$Zuw^t;cQ9*j^9HX8kllPqc4w_ zd}DokNn}})MwYo_;^v|@{y~gdOxvfxBfYXrnno?j`RP{rZ!kJ?+FI}F4+pa23lbNS z30uusNThzS@}T-Y93qAjh%XgNRaL?3qZwys&^iO%HL~Lej#8y7%)OFp78c)za274J6qSCu_n$*q=uF(y1D{eMwAd46!Fn?3Zluyw$8OEUzDn`?^v`VxHY^s%UGNZ-48~sfj7rj=Y%t| zONXTE{hvHJ=WZr$@J@B1qr@F-{6;f7KJ{kL%OY)aS&5Gs<%z2RzRqbsbbxn$dsXh$ z!!}t^WDr1N7YP?o8OOhkma#kd%tsd`%8Tf0@`(rQ zUSHM=d?;UueH^s++UDrE=t;V{F>r7yqo-})qD9qJxA4M@$LnE59Pi%78KkQ~JTK)g zadau+;B~`te%#qo|A4k=YOrMm=Gb$OP($bls3I=HrXLe}?Nc~B)wDnI{U^vfq_E7| zkO}1i(ZWXmSSp_bsZwTo(ZIe%6Lw%pjZM4Q4&G zW^br*^YNmdsP%oc%?%u%SCXuTZvaYy)<HvazxAI4D5qwzKQ00=)l@L89)~p@& zSPFfKuNz;27fZgeoO~7;44=(Ge;u1}VyTmEmsEiax;YKKnsU8vXS1w;9bZ36Ia-y? zSpi$MbR=f3&7cJ1NfE2xIPjRtakGoA)ri^BT>RyKScN~T-XHz$>UWITg{P@2Gu#Sw z0u(wd{^_r!1B^DGA`v?jBKT=C=&Bz28GvI<63RS+Sf*1=)C@(I%JLNREOz1P=0wTZ zK5ic6c$x^q1I$MXe=op4TO2hReZx;v+{EEEwY<*EK(3B*xU?Y8y3~^K9c`ItbG-OoB zwOHnHvA>Ylz##K#-jn!qgIAxPHyF{8J>eHiT=QNaLMCi0yKgS_IJ2!1l(m)s&BuIZ zkbxmNSHB^o(dB8y)74iYqTnyjwzwwXcWB(cWn`;#$Gjm`K;mb+GqP$_;D!UOkAUX0 z{jMmQX~S<)jq)42g3{Av4RW;N?dt{xN@S`1*2WdE*&E^3Kb{m67hms=Hj0!wS{qSo$|KO8$`AQ*a_w9afmI;?2dP_&Sglq#=nYlqm` zXH<<&rK0M=5$*tHHvo9}TeJHoymoAre;QR9ar}XlI*+_YXC@PCOw!^t{$tj+N{vNz{2Uz}IhLxTv;?+6!% z3a!(sM2~aPcw^A5Gus5HOn{;)KXghTvW3ls1DZ5n?7~mB;3rk~UlwVZPvstNW@XOv zKM(!P@Oet1)_S1cb0*}x4sihMyC7@UpN1p_+oc)8JCscW&}05#jl|8fTX`*>JI5P~ zptD)KBS0(ai2T!F=P-1h4P z`xl4(Ygo?;s8y>ecfBsdBm3J-tRLx8Xlrsk9>Oj48?zEy0r}KxML^tcpXo61u8!SC zroqbHjUd9&eVL{y616okibO{Sy+$*PMga@Zf%)_Afp2{j7SCs3nf%Hu#-!2JAd+yq z7NAa4T)s)SU+g)0JudVgIWv0R=aAr3y?l>o410ix|7v~Qdo$zS(6I`L?;WB!R&WcB zQ*0zC?Jm*)E)ZZ|-9BBi3=PkJb&UVJo*9cJi;Ma$yTW^gHs@Fh@`uJhiyH0rE!%OG zgc41JMQnDC9{HRLr6p}WP!7WGzvc*K{_u>SmH&BfX6T5HOL_T6_YP} z_Z1-9r#wXmz5CO-wm7RjAQvxv%H;u=1Rr#EV7)vNz`p1Ef3&2(y=TZwTpw5=4&Q{U z9XN-~qz&ur(!Hl-P;5calHm*3G}qADs!Hr9#H8q0>l#2Y|E9gawq0l2{rie73tw!E zr1xgpmu5<-Yb;sz@;%HLZ-!Kfz_8xw&Tpxr+NbF-y1iFTdJr6?kyIavvoqJEd|19d z3d+^V1;pkl=Tuh@yPS_<(@|G01@9Q4?|AUBAQ39EnRh26vI$k%<3Sp{43|RvN!$S1 z>F8S9cLJ7MdEm#Sp8{9W4P84YoA{IQTjICl-*BDJ@_#s!%#h8guBNI!$T&|1-Cifq zIz{Xd_I5T0c;9SDc1-Z`B94J8sM$t@OP3ZJ%%~eq*-5Qd|16E?8&d>?& zt3!a`om7>^zor6iy`<@PG|@lDJDfmI;$K9&kJm>Ev@Db~?6MSoVTuxnEV&C7%z zOzLSh+c?s+#7C{iymn@}d!dE~$kg6Wv9W+bn%+yAT6X%qHliw4q^WOn7c)}Anv9N9 zX7F#(e)PbkYFT7Cn;u(^;q;GPlye+S0T$+yr$4PuttCU62bC)8gKZmop^uNr|_iYxMf7P+oiElcl4u@y>mI*Te?@bVeXx?5xo8|LD6y3YH`C1BaOlg_^5g?dyZwt^Dz)b|Ntlcv~8@wDdNPuy^tE!wOh>Oi_ z!vfK--ef8}+c9U9yp<}|`0!#Tl2z0uXC?$PC^ua`mDZ&;kFF}{UE}9BE76^yV{N*Z zf%m#{OZ;-O$=QWx?a*AP*t^HHR%hGo{qA1gI{&gzg8p(qikrU{AF~9rl;W(b|0Z(> zd$&m7d}6B*AS5YGhJ-or+PkDhwCk@`2kl7jYu70A#GNRPuD_X^4C2$aCEDy6 z7_Kdk-YhdTq}XwH1raGoTFGe^6~#ndgYm(UsLS^*ngX=9RZ|N4%3;qsI#-e=@@}6& zZ!J3JERpYfomMJO@nUL9i7gp)a&>&>WeI1vLXD^z+D$Um?)`H`5*GySkYO-xG;Cm* zwmfKaHat$gO;h~dQh7;XeB#Tx=mKl|$cX%hjiK}#IRynwE%}GRO?{F995eB*{A;UE zWxpJ9dSk}^rNPsbLlt!Xq5aXs++k*GwVtb!#Yi;Dr=MOo+1t#4Y`m_p^R$}2q04>MG_fhUW`NnwL{)b;!-Y#R z15-f|N}onErcaNrZC}DbO~LM|yM^wqmc9DCC2=oN0nw@%U37XE#2RKypX8)7*ByeK zDAG-fMscczu}^cDl>*jIgZ)?8>EJn{A7jAxY2Ld;`Qi}`9p?|a?*d7EcZMFC?^y%% z%Y?*D24(EBjTKqnRjdv?%aPk4@WOMQp;wc^G95Jd)nn`)XI(mj^|W&HX!7eV(*mhcuA#;xx9Z~r zpFZ3h!%uJrrP9q6%q|`YXA7cTE9)ZJ5YGV%#} zWiO7#4NXiiPJia{Z1=q{p+YZTeAn_OV2CM34e1wDljeq`$3Bo~l6vPejp)Y(HkXm` zb!j6X6Nk!fUe=2FFbt}Ai5sJR>C+*$sCVM7=gL}5}gaZfVS?=*)J^$*=ZycS9)Xv z>eCg{Q_GMSK@Ygqd8(UfCmJo1F3VSUUf-W9vPj*@s<^$0;D_+T04+P0f37?s9v%N- z_OafF0yBIM#xfst;6Di78cRxxuB(6b~1+>%}FZfMeq zfi4*&h9!gI$D(1ZfS$@${Nu#_d-r@A+E}O2^OD4<5z=)9$VY}q{rJnokzGK(>)=z6 zpK7{9$~APV8q(qb;F1d&G_0yry`%52;Yhdly@QqIVem3du0Bjvh1o-@q zr3Xh;4mi9Uqc?np5?D<@JfgGRb>-(W$okh0()O$}=lq=7ddi|Oq^W^ZoGz=(?2ZT1 zA#{L+nqrDBIU)%x+NGqXrqM0lubBLjTYsm@2={_YKNf)~R<)>cmGTKFn455{bvOl|tessYnJ z9Gehr%A<_bsK7%R&7x^i5dJc1xRiuFY36GbWNm2HcM6oG;-;WkpWc9Sy7%Z)py^{$ zZycQB)ry`;1be)S4c-qv4tE5G5nvFXNTl>V#xWqE4WDU9k4YZ#XtEVO3a-C?OoN1d z7z!+o6Oc*PGGCJPm6CksfXch}z=A3<*vUb0<;d;Y~7FF%SPc# z@WG<(EA`X1W$}8${qk4g`aXVq5$cXEp%oIw3=9_8fV9P{^b4-(L1JHuWnA)DigE5B z9MK^12_qS2*T14y#<)ll0c23Uj?u-b(3SI^DxT?_T$6rl+$2kq&woq@Ewi4(Lt$b( z?hfhYC+WL~mpPKZ+274RSiMLl$(QF!w9-{2 zIR{3*T@dBa53_0?ZRR8bVP1w;`M=JhzdTbEJXy@q7f6s?LHWZ!H;vNV6gs=$&e9l2 zFp&_kZNjMaPGp}tGg?_V>QgO3}0M;$@7aKdO`oxu>l)r37?W8n2fA6 z)0@q7!trZ~o%{MubqR{>D@AYYdXX&^AM*#=(!oS=md=Kmk zHVh|&T$nmBNKZt1v*paHLnm=2&NE1M0YwcQC7kZPe`dSeZkyn;(@-;l`YT~nViu4wIr zcf!{4%QqxoVm%&N4rGu(NzOGIyrUC=5u&DMXsxbz(m=nVB7q$BO@Q$joAz$L^vd8yO zy=}FJeY~pKb1~&zstrb*YbqAeFS>E=%ar&D9W+u=*%@uGW{Tekl zX{aRJM|<44&OD7x9mtB{H!C{#=>&W~!v3cElI(Y!eC+s#1qo@}Jlrbq;<4Fb z9v@C3x*2y!MQTVDDRj5YUtI-~@HnH}^gal&hlW7il-6<$hTQYD{RTY|6Hstla7U?r0WnOlSi4XZNT30P8f%BXPUL zPjPEC19->uuyryGm3r|N{up@~R@=DqEs`lML-n22eF)p5ta_u3Q(ya(xO39Q)NSot zGIK6x*4&ZgKjg=qarIy{e!O_J{PIoN&o~}iQIrMQh;+ROJ*2H5YV=zBiuycpdXR`? zA#6I@{zmNAw_jq_r5k_XyYlgJt;|Yc17r{mH4fg+n-_lq@mmoff)NSP<5{Dzys_&z zbsb;Z?4H)1wXs$O{>OhIc$?I(2_@(EL)s z<7okTt|WD<-TscO{{BAeOb+Ws`?MHaQDv{=8Xt6Z&D%f1X~Cng-U+t}Wl83%*vL?M zk86w8Pq7byB!SD*EUmFPzmDqa$OmP@ZF2SuT5=5ZPFl=fh&w{MFi$vGcDNnqWVqKO zKhXkZSiL)e!D9uD5G6yHq!9UNx!~^=1y|eLLfoQl=yj;qvL#Ep0Gp!llh!56z>mxs z2)%kuuDhj?;*3eO$C*QnZ# z$@~05!k}Ti+#lfYb!#4sL7shbc=fX06z#Y@s*CEP6lzD4GA3wJpSw#qIp=1Rv~bn& zAB+MU!NqZQ6AS1l(g#F#PZmlLZdH>?KdD#?>+0Iu6}U66#X#g z&_m|VB73^WwXwU@d(d8%zHnI^x%9&5@H|xBQkGCIbf~7$yldBksZg$~sR^UiJCTW@ zN#(G%25(#|eWQ7)5{)Vc{%@kk+Wwgu+-gp=b0(grEZw=MYnfM6I)^^GXlbS&sLmhP z=}1~6DJT^aX-E@M(gYuRexUaN^g^OFSGi-`@JQ|H0Q)t^@zwb!fLN=XhqNf0|opSWL@{5^GL@H$;derCjT<~yhBMq;`5Sc?R5a`Hsq?}+3h zUt_enUaE0lX1R7+8pN`nn~9!+CDxpoGML*+AeCnVGM-K2x_(Q#!JgB!qFn`cWlyj^ zKiMrb+$csc0swXdx&vSIE&um?QLc){Y96!?I z!yCww6riZDt|II5ymZn%u6Oh0b5rl!_q9Ea>GI*dZtht)x6y1%PlSmLI*dzslA-t>(yae3{Q!Klf;YAmaX$MlJSZumdqWuBc3Rd!ma$` zwLGn@tXHgfJzJwT$9AhD*KC2QsCE8tki~5W4;yQCOVO_nDt(U?imQ*`a_eg~P(-Bb zJ_<+;NAU&?e0T4^k(r(rnrT%a6B~b-G0RKkxXQajR6;_Ir#o*y&0w1oUx_U^oy#kL zl(5xL9mW+b&Fnv9c^sg7--zSE2bC?6A#Hs=fi>BE!v&}QA(`)V7#y@<=vs@3nW8-Y z?ZRwDa)PNk9NE(-Cmv}CPO42>d@=}F% zry*_+Ja|~FRZ)!~M228XUSbmGu-THkhKyLW*ro#DK7K#K0yvo8jk!^)9FdK-biyjo z8fEyOTPQqjY}XN#e4#DmhM%0gdR{se^nnM@^+5R}NawX}bP>jwWYmjA?+n_5w6L*1#L}Lrd8F|68KjqObJW^*t@nC&*g~~4U%A$1o>ovE+}v{Cvy{vL7()z@%O?tS zdr|9!g+e|)ZqvuFbA*p=r(4M|7IZqlVL-L$53#>HZp)%}@u}e?rO?SO^H;-^NTbdb zZM<#~kmuP~nT?i?ylIRzORPp&FD-qD!1pM0gEIkbRey0ND1SbruT_2lN$3i*)(S9J zI%_3Wy;&W&qQ8`zvv-iC@#&{Q|8WBRy?fsJ0DqMC7r)C#FGhWzRFl^>{(izVHK%ky zsOH34#9c24B0n1!-g_fIPNshE%dzXK;#(u|qH_OTG<{NDR)cI6+iD zWKJ`a09`j6UqInFyPPxSt!;NDT=^&+L~EE_$)Fk!#toT4CpEp^Y~H-h#lnS1Q=)5? za=Ma8c=CWtU-cSpQy(x@x-oxauYP1izjtr7=vvid_tdQnY~@RwIcg8q0z9ghUkgBk zmKFy(A11cmn=Fa#4 zlHNsleOxbCyGY#vXXOnyS3ey)!h!1Sj_p(6X*ACO)_7FnZ}>Lopsbw)|Ge)gx3Cxb z7Q8Aa48H;7t5#bJAYb0bfB4`|`=!YH$z#$W7SQZjo_fIc#otGdU=SMsTT>Ta zNb=i+9vGg#+MFNns}gGkknIw5!t7-M(5c$25e3e&h+Egrw?3lLi0)kPXw5T#5Vl4I ziJPhDRMUZn#dY%Epz8o6x*j4iWjf2SUk?9|)T`)dnpJ(=63Ju5fh zfOiqZ02!&?!9JK~Pfht6VUSM%wd7vBSl2=Z-2fydwveDI^%TO&rZQm|01^Mh?v|fH zMt}FTq09&-l(#^8*!t|L_w3BNL92+PBOj%$twe}9x$XjpLQ?hK=K%fq7BS?w>?k1H zIQBX>5)_{5_ZqM4@t#^4c5>XDLPUVDN&V=1GqaoQ@o6!tNSH;pU$ORk zS9pRpuLv=^GHzzau7iL&Sk;vFKiB1N$TyH&@w=~4YA-PkQKx=6AJNrb>`M%d0Koc! z@j64eel-}#0FL&M+7x^ult>1py_tiydx6*4^t1+HSv;>yeXsGbSiHpuZLE!%YRmkiOQ9W?wT8OI{j@9^L`>phsw!6OLUgb( zQ-vdDuy1Z1G_Sp7!dRJU4^A5U& zR~;WZ0hRhSOFU2G++L8tGVO6x<8MY z#b!^?RgZyIck68A;6e2NX4`L@`D@wgh5Kwpc_=<2^61w4NI)R8vOx1!=a508MUb3# zXuPQDfT0R^Pf#`yayKL%nWfz2i3W_zORfkrxeDP`B;9oGzk*YD#Hpi>wXohAVHz z7wRels_DZSGU&)r5GgX$h_UYEwn>(yfLNS(nK&XwYWrg7JtfHs%)lV zBGLQQ9g|0N_VW4lei5q}<>Aac4$0K;)`Jz-t3?;U{mrOBs=x-l)KT82!SJD8j^@0! z76((tm`Vjl7t93357Dpi{3v45`le7vj zNh3Q#f2jJrLKlz&5e(mC124(FC#7r3MA(o)pA$*QCBeN<0FHz&9@~WBi_u@npzRVf z!28a`|5on)#r*;ep~wWp1l7W^{Dy?s4EU~oYp$eVWF0QXt@V(ndk3jiFMPmY-w9m@ zs4EIH$pj@dpn48JVMv~AiZFESENgQ>$4(Q&sD`&S^!hTBNpl@q<)m4374Q`e{*B zDXox5W}r_hxh+et&h$Hm{MUZ`htJxPzH_p@G97$WuUDum{oSZXFRnkz-Pg8Z$mInx zg$AIQ@$0-cKrNzO3Vbl$i4|M(@r8(Gr@NejN5lfqLGF#f_$P^z-V9(A4&w8`$vQg;J|UEMbm}v>mQVl#Cy}piqosYC4=W7E4 zLgV~Zb|cfD@r}I1ZKDr_z3tLR0D$@j8J$0-F8#s1sMGlNiooWVEmnBy?H#qP3>*To zPNAnI9WWE^F(W1f&v{?xzb(G(k=0OY&YZeoL4m)D;d}!bu^oTlm_DlVTzRip6W1ue z*s}w3XatXH+b{C#AYfg@*(>kxaV-XfLA2xARC?G zOVH702^R7j{yMYInu97opWcd`ERe-d{FS(oGw-gG3GQ~5I6{*#Id2>NT z4TYCzlS|wLugprB+LO(;pI+@+u!qCPhLMnsIao^(x92Le;G7FSA|Zxq?a4)wmK_@2 z4Akf^dvX66gR33*#*(>xBg6sKKS=%cORTBRK72wRhyowV!OUG1HD>mXxtrb2iF6jR zbWg)3dWi)Ior2e92;Y5VZqa;mP6i1*sU4GfZgnN8x=L_%ylKbYRr=+S52q%t981e- zyXc3xsi+{==Y}MCJr`$=o!)`7Hx^ADmpz)BGcuBj!(wAXN8|55Nea_$0*vlmU}paJ zPy6UE1`kEwi-@ze5rZDh<{}is>Mo*>?Bqm8bYqk+X5?M5DQu_-Bl0DA%c>gf)oyzx ztcw|0%p+8KgDN(FB|>0M2xUzwMt)G}ZFILPD=Kf+0+K%L2x_GB)4jlEWd=)>hCO_p zn9zpOV$kJ5?AtEQ0JGV|>HzmK%rd_Xiq7_M75MDJ|Mly6_M4J&pk)xV7Zc^8VLq`QVnO1usFFZ;y&S*m z2S;Zv57aTk5VAOQ2nJX*e*iZBL{f6l9?6D??uU9W9EY3Z=lae__ugn}XKU!-d&Em< z6ErT5P-K7tgQd__A4lpu6?n%IFX&LPB_C%CUtjlJ}Z@7#53#ySiI5 z2+j^z+X0jm$Qt{5(?etxGNYGI1|cefh=)$Jx}>d zmFK)T0iTK_g|#cgx9v`kHWPHNv!5hk0#+SZbkI|Oc*V#~eLugG`X|ip->eW3k(h4Pt4-C@kaz5w7rfs_J2(5?zt%7ltg6+!Z7N-p)dw7dQv2wf3#NO> zB+Q8n(mO7#G@r4fQL`&GV8U^sKr>5Hw1^0fwCxyBz1g6dhUw9PIs```kuzTHMjcsEQF@Tp2kCBYg+wmSn_$!spaK0Gk4wC(|kuy zXbFj=Qfc$5p{%0?%@CcubCGF^S*k5L1+o{`BFymxi06>Wkqz}hi$dtJ@^S}LK*N%r z0lN<#)rP1_Df6eZmxQuPLHK`c{BAWrFx(Q0C_%PbaqO$ zC}ULO;*JL(&kLg4QE7>hha{~ZH5(s!iL}ju>e%fDLMUDh0etkCW+rc;V{ngZtfj2n zl|S4w{HJ*$O*@&s8>x@Y504uMIyix3wWOua-7a<22Wb8Q>)Z+~|DNL32Lxf+P1(_{i>1>z1wk4Xkpp-M~ zlakqEvsq)6ghOfIJdk> z4zMc!&!5C&+WgsWE6Jes-7@Dh_7dg%hMCy>X2UN+GhX(N9;$9Z`-*}RZ;Jr@5&yyT zm|cgdX_uCqdfk>gV{3bMNuOC)bwgRH)Sj(i;mUHI@TW$LiGoK1Ok4{9{iVc3ALYDi3uA%Y&1`=n$h;Y zw_3r5%SynqpOyqo${DCK!+%hj z;ZS1y$e6q9vb)~B!ltRv_TJHpkjdfb-JYrLfpMJtBheLUr(vG$%}Cnj3mrD+#Ms@v zSQR1YD@W617dw>dqAdkDT}_{d$V*0jp9yh~emyoOY49TP{UO;4Z)KSez4GE!+FqJ6 ze}~*wP8!Am+Z46+!J>DmPf4$2djRKN3=kxLNn!b8S?MI5)h-I|yT*!&dtx5X=qGi~ zmFXyzmi$%w!7t2I3en*?W6Z_MH@h7i*r3Un_ku%yK;siUWCO zU$MWdyB>B5Q5?cV=|gqY_HE#G<^Ktq;kkU6tW25AU60eaHI$j zAyb85FOoq8iKh$w05Ne=3J}b|1R(kJdlwmWe4Z!{oYiDUYVeY1;RDiP-)@m&;hR9_ ztg$?SD`6YJR>5fe1<(?A9+Y&p1Lpt?(>O5zydDql2_ne>=Z{!W=KTAA{=0AgJ%|3i zR{m`h{@=B?KYFNKyZ>}Cq8(PHz_|-9n04**=*gOA~A!>5uz`0ZPqwCZA`-vAv`VbnlzZ?Arhu)-vjFWBpyn9-^$|4iJW8%oRoK!VwmFY zViPX95iWk>O*S|*aVMwzZ zT-X@P&epa3_(ERSV0c#0hPgiG3;S*Vd~=HD{{AHnO*`pU<3}s?lJ|`|zS3C?gj)7o zZE*4FH^U$IGkf1ZvHaDhoaQjekbBX7-1tLMu9chN>IV=0h-7nz$F8)8l-)C;Z=StO z8~*6n1aJV7{_o}{{K%62Z@uT!AYN1{C=O9pSmP|0i`@G*sdcx|>(Iw%;as63+J+XG zgpKKB09j|l7qAwGQu}HjDqN7X$kkyQq;;f0w|ym5Wsd>+Lm&%nLDy58)F7k2%g7s0 z^Ayar+rpOWvR7@`hDRf}6o&lINoSyM&@f9K@^d+>BR#K7Ox$iYwEDI>>FoN*w|*}g zFF+q^bM-MTNZ4cJoBVy2;~C4I5*8PXq9Zp9FavIboy*1Y-L~40vO(ix-;@0 zt99!n;~GULH6K)c-$V%3IFfGl4cj5G<6APm097SU8cKfEF71EwRX?Dr@jZI-N)@Rq zkbn0}!{Y3%!znk3lh{vbceoqf=5jm*Euvw*BE$pP{jMZ=8j2f9|u=5pOw$}P!5 z!g4Qith(063I6&pqK7O1nf*ZD{uS8yKm9$q%o-#qCpd1$jtJ&A*AC1CbOZ?q(XEse z6ybF}JH2e*U|Jb^Jl)THJ+O+#hgmC9KlFao(@#RR!9s>_>26)xRC&gLJ2@2x)3O^% zm@4(9?yFf315*n;F6ns_YEhD%a&Kc&W!A-V0Q*4hDI4x-)ae7VDU$VFw zD+h6`Mz2G?UjnDW(C*{aJRo%};65pN&)_Ki0mZ@)%mXhk-5e`bVR`X2P3K%jwe`8o zXK7abjQU2YR-}i!F8RgR@BOd#&O4~7Y>(qu5Z8uODN>XYB_N7~CJ;d0%8weM`rBXX-n70=j)G;~*pwQ+7+ZXo^ugiZ_?=D{ju-!(i62C(XNl+yr)$O-r5 zLJ8?uJ#J=S0B&v$NV>Iajn(hv{^4;m@(0nyuXL<_7excwvaRxQYs9N38G-8}q?9cz zwtszF1g{dw5CayR&-RPY2r%YbtBx6>^yp`9yp>t-iZ77u`znFoy@8uD26V{m#4&3C z7S|a|fKKU!f0H7fy>26oyYzwz-h9$arb(hAlpeYBw2bd_$*|5XQLld_(r#Vo1T0$m z8n7_|R2Lm&B5mqS4|LWcT3X6~T%z7HhcZ6Rn4(m%+RRV5GnZxt2L{y-@~E2%*KOT@ z*<9|?n}UfY@Q{kp@*YW-)Fwjl7u=F(&$yPN?Rv3E3Mb^Az98g|(R7HZjRAAK@DZZw zUW1wZDlLLO@wrzpEWSkUXO|%*omuYvxJtUqz8a}gW*dxdY*9=SkRD6< z-bl|6Xiw{N1MoJ>v@g|jyh30Kk2VNe%puNqxJbD$KUAqLr`LZfZvB~R`~#lqAo;1;weV~~$`GjD!MV;#IVqAu(ozsL zPdmVjwHc6%8qnz~m(-)Bu{%8c$j!WiP2uL2ns3{}EJ2;rulGuj#^nl*0&Kzrp;eTc zTT)Wa*u$YxZ^AS32YeD$PF1}d9x`|_j6W%*G|#??T_si%+`W$7-u8JpMRu{)p!ks! zjR8SmMRF5^F+G#H>;Yo~ajx?>(vT-q%$i5mQTJcGAXn8fi4oUAXi zSN4r5=Qfzo?^?#*`LqT1W7;mdgH3Qo_i|Oy?_I;+^eI>D%4j>9_D%5-pVheMu$U2W>*GJ!n;2~MasRxb>Uz6@He)ESH1M00 zK9j}<9Q+~1smVrWRR^%hF_CRk{S~(YY!_4Z`V}oLgmHZp3r^OYgqKxR-f}F@;(qKB zOe4<6Av*n{BxlZfUXt~8JRGS2C_%qw?*222{a@W%IxxSc>q?u){LT154-a-=YP!wJ z=)IuJH$HkDwtydAt*Lr_@Qvn#tP}E(c(w2nT~<@H%uyx_9bpQ3w0qO20?5jR{<9NL z%;Za0hA}P_RrNBI_Fj5aqZt+c9$M>3!wqzkbTaI1d&No;zQ`t}eF8jz{6vH?W|1s~ z`jWvucEAfZvk`EyUYZjFB)oW^ zc>%$K6_0IDi#E}4aw)ajXmmOeoyl$}8Yj{EA1|r9CK4^_3nQp&tPt8LCIE)b6dxCm zo9;vX`PT{Cu#G-`p)p+O)aKJH$J(;$Wc|cTF=heUkq#YbJG-f*m*CqgWNX9AHKb`;bw z^>7M(iy+)jMGF?xvD&7w6-B4B@!wm!;A1X8UJ(r~Ne!UBA8SGM5MSb&l2ZUk3!pBD zBfo5#m;-k(W4ITyhuj3QO$h_D=EV*sFy)BJaJ^>_T-Q~~Ew*W?Fg@>w-VgQmfN2WoYS` zL!uOYpz>-%5)1)cnTJN%vV@mdwpOW8Hzqk=)&RmDfl@iM^xe7pPL zyTXmq9jf$D?>mJ@1a6)msheTqV_Z?z3>O{;>l)etFTNndx0!7G@{4SgpeV6cQ4C4( zW|-PIH!PLrN9TBrzhVu#A5rwkOYy&Weuws&jw9Z(0MphPh2w6Ew>IYBpz+m?GT9a}XYB%u=WnjFPx<72RmwXG-PO;?m@a z2^HaM%R<+ErZ3HsHQGblgPQ%bCkp1(P^cB0D>AefV=kg{J8oag99XymiRjj=zRn!5 z6Tm{H8;*|oK4>PZ1N3n8NifcBCD&Frs8-vmho7JZXHVr*j=GeTC9e<8JB+Va+^CYg zxB29cyKKH@1+~7&o}|su7HKsJF@=-8qXpfIh}d^?$So2ELD3q-QO9i_#~R>SC#Yrk zuAcPvK{(0Xw_U`k@Nezh{hqVkr*yZq#F(i=7F44xi@?wBlKBkf)UqQz*6P1il8NI{fJ%dQ83DR@rcv7+G9xtw#P-)q z*T>7-gNFTv$H1fh%h~D$l%``VxKhDJXbD@RFw+P1ylI}WIMoue{rs@Tlh?;AAVu5` z<|LPvMDgH(5JGEnGxM&uHq54+zQYS9M|RpPyc5gD0k5(Yf#r^Qcnz9A^>{$)4xdY&srNBFr3 zD(I*zobw{Ie_PtlQ^`QC9&Gj~oSC-P~A@OSTn&&~05=)`p zJT-56c?&U|)NdaeRDQlXe`D&2%Tb|OF|qGnPOb7%toW7P9)(r<%=wfJ)!9Fa&^^~beePs*!P#9Bn(+)WY}?#QET8`; za-xetyx2AS#6>}^u2WfK%@4l8v6q{1YHcKCAT2$iYO2iH1Hf9|xj`QSf3$H;5$mRx ztw#iyR?t&lmfw}(>oGo6D6A~rz z4jz)5X*AJRAkzDwYELfbMIUuiM(S~*?_<{Mm#+*RUjerB_YVyOCk36Vj&HPCVRUBY j>$bj;tobzxDkKHEz_K literal 0 HcmV?d00001 diff --git a/public/img/mimacom-favicon.ico b/public/img/mimacom-favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..0b247eb6baad1da6a39d8bff70728853c3083c51 GIT binary patch literal 38078 zcmeI5U2GLa6vww|peQH^jpCC;A4G#1eKhfb@Mfa6(n67tU=;cGGs=sJZKzt}7bbuR z))XI%3aG^>7!y+j5kF!;P$L#wln(_23L*$?|DJzuhr6^p+?{*(?)F~JHmAFt-90n& zJ2PiyXSO?@S0X>tr+e~yjQ7qG&%4s|ys;t@CUUA*I%SUmE=;3IZ-*Q+5Bo%zC+2OFNVCYB zBFsA(Ob{7OHu=~p24Se^uM%kzX%p!Z8R#72P9K@Hi>wlMa!4fZ z{1ke82ZdRKNV%&WDm;|PeKjHnL<*fl(&^tX46DUAm4vZ__?l9=zFwpde09=n!^TgR z^%X-OJAP zu}$sQCQBIGYULOYgF1g5kT!RiuxEcs`NzZH5TB`x4TL+Nt(1Md461zm`OK#L<7Lo9 z{?h04ggu{|m4Cbp+Q?q|Jy#2R9nXoEJd=loFV7alz%b|%zUl#Pli9|lUud?CszN-UdNo1Df{#} z<{c6BKgrmD@3wTP|4GdMn0KSHD*siN0xKSNliEAo^E!8&TO3T&?6L0gEWFDtp5=1^ zGRUF)n)kf2(ou5-oVQKyx~F&X{m#+gg(>dwY;AUn=getf@^JTfeD)&$tmoU6f6n}~ zW=|U`|D5?}<#$Z|QU1!`=CKRJ|7-d8_4^ZOf0e)T&sYYExc`|k@20H{+H3o(?QfFp zZ|525gOAAR`Af@x4*s9Erw<774RM5B?EXjj+q@5A8UIoK%HK{P_)Ia4e`@&;wlPEF z7=KXy%HK{P_>B6W==!VL|J43}a4l2+Z{wo=NBxg&Y`}H=pJhzPAA)O|_CJHUsQ*#_ zQ#AfZ#=g5cgUh)s^t<)$_J3`TO`AP@*=+ZCwtZ&T7j%YsPjdW!(q+JjBS9&%haKDl zR1b4wvtfl@pY6=2E8XIld^vDhw)&Ls@QFi!-+u~Dn=Q1v8>n-52bBGb zBL{5S?BU1$0`40Xo=yEdc3rkJfBXzgyd-=a`LM^9wYJpR!*_oVObIz}w5GwXC)1e^ zUJS=(%1EGXdnRrD&u@7@oc?@pH#(aZ^iNlqkj<+z_|7t5$wTh#i$8AqXTGCcDY{I0 z`|eo|zFgzKEBrC@-dA7Te?M|-`1JO@vi%2u_1^yu_r1c3?~Z@|7C>JW#kTQnVE#=2 zbsIkP8w>BwuH2h6J$hSOpV1rlo^3$;4wItn_Vm>|S^)Mx_WcqacYkVV%YD02aqQd( zbR6=ZbwA$oqxgQwd)&N(;#>Kcd-@Cgj>abj27B6LYB_N9&q5~}KK-tJtDrI)b=Vt^ zhfjZ@U)d;mjhbJs`q+lHO24w$w_V?y-(Sd;Ta@?DzZp2$QM?vl-k8TInMJLup&B^* zU-8+1d0I4SV6!*2Ts{xryQ#&pkv+!%P5ugD|ME28)QS9ApsNe`WErsGb$MQp<9uz* z!%I^Oi@hlyPu=c5J{N}LKSzP3Gv#?!o`3iZ#Ia_EMZN9W2|OuzF!?FOJ;xx|E{diu zbe;vaehAFDp+A#3Hv(U;%Wb^K*pKb(>gQ$rbY%Z{@?e9U{s%a0dS;CU*1Zbw*~N7` zeG=eU%()E!20FD zZ`)-4M*PMZY2VCP8_W2=$AJU80nQaKodrBF#yx$!hdyfadnsMiN!{GoUhvxi$NvU? z{TBFmX=)rWrtsx?X*8|f=3-2;_=GOFxu4z}LbTbZq z&*MQU<2io2!Ot<`ZFLZPhDm>@L~K(p*Knw()1Uyw6nHYXhwZ(eWqC`iX;3 zdLj1aTu(iadLsAe+DN(EfNg3`rgCrC`}cAm+vEljT^rur4(!j@+1gq^=S;`!tBNi@ zqj8;bu9dChMg8qTCLG7%SV9$_sWNfR=DgG+Pi$(|Z8q!Iavp(mIh;@9oMx*C=l0F| zR^~mgLTFQ%Mw4E?8^t_uoiygj%-3?xuu;T}-;XB~vT@yT%-k^?s5QqW=r)I*_sr?^ z@ipfz_q^fl>F_fDaZ5V9)PG!?4ll7Cr!UbXC7=YNCQzGJXsv@S>1)obzwPPpGXJsP QC-{AZ--q~pi{Iz`53L3ItN;K2 literal 0 HcmV?d00001 diff --git a/src/data.json b/src/data.json index cfd4b37..902d335 100644 --- a/src/data.json +++ b/src/data.json @@ -30,16 +30,18 @@ "placeUrl": "https://www.docplanner.com/about-us", "image": "https://lh3.googleusercontent.com/pw/ACtC-3eAdZYp96so-BMbxGty_qum7xEBApzC39b0q3MhLujo6_7-2acXmN-Uk9at4yzwacVdVFG99mM3D9BgZjqz0k0xP3Ytg_UR0lGkebzs-ATQaRJgEh9-EqC-v69EdVg8XzDAxqh5-StHFRKUioLIMRSGLw", "timePeriod": "2021/03 - actually", - "contentParagraphs": [] + "contentParagraphs": [ + "Worked as part of my team Umbrella. DP has two main parts, one is the marketplace where patients search for doctors, and the other part is where the doctors manage their patients, patients’ episodes, and appointments. We worked in the doctor part, specifically patients and episodes. Among the challenges we faced, one interesting one was to take parts from the big monolith to new dedicated microservices." + ] }, { "title": "Senior Software Developer", "place": "Mimacom", - "placeUrl": "https://mimacom.com", - "image": "https://lh3.googleusercontent.com/pw/ACtC-3eff4oY4kxz2EnFykM7JL1eeed-Cjak9NdJg2qLBMGX3k7DB2OiWxlw1abPi2zDfcu3Kn-RGS3z8mYMn0lwEq0rX62L5-cSjYHmulDJaS227hAJOSEM0scENJyUzz7UnYRnLETsw21dtC40RKiQ9LTpmw", + "placeUrl": "https://mimacom.com/es", + "image": "/img/mimacom-favicon.ico", "timePeriod": "2020/07 - 2021/03", "contentParagraphs": [ - "Worked as frontend ReactJs developer for a company's client, an international bank name Openbank. Worked there in one specific project created from scratch, created with good practices and patterns." + "Worked as a Senior Software Developer for one of the company’s clients: Openbank. Mainly worked on frontend projects on ReactJs. Also, conducted many job interviews to new candidates that wanted to join the company." ] }, { @@ -94,14 +96,24 @@ ], "projects": [ { - "title": "Rulyotano.Math", - "github": "https://github.com/rulyotano/Rulyotano.Math", - "nuget": "https://www.nuget.org/packages/Rulyotano.Math", + "title": "Rulyotano.CrossCutting", + "github": "https://github.com/rulyotano/Rulyotano.CrossCutting", + "nuget": "https://www.nuget.org/packages/Rulyotano.Math.Interpolation.Bezier", "contentParagraphs": [ - "Dotnet helper libraries. Currently, the most interesting is a helper to interpolate points by using Bezier curves." + "A set of dotnet helper libraries. Currently, the most interesting is a helper to interpolate points by using Bezier curves." ], "image": "https://github.com/rulyotano/wpf-bezier-interpolation/blob/master/interpolation-bezier-curves.gif?raw=true" }, + { + "title": "rulyotano.crosscutting.js", + "github": "https://github.com/rulyotano/rulyotano.crosscutting.js", + "npm": "https://www.npmjs.com/package/rulyotano.math.interpolation.bezier", + "web": "/demos/bezier", + "contentParagraphs": [ + "A set of javascript helper libraries. The idea is to do the same as in the Rulyotano.CrossCutting ones." + ], + "image": "/img/demo-bezier.jpg" + }, { "title": "Tree Extended", "github": "https://github.com/rulyotano/tree-extended", From de6a5142ae8e75ceff034c643b9b6ca501e3da4f Mon Sep 17 00:00:00 2001 From: Raul Date: Fri, 11 Aug 2023 01:09:03 +0200 Subject: [PATCH 07/14] Fix minesweeper url --- src/data.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data.json b/src/data.json index 902d335..8b76a3f 100644 --- a/src/data.json +++ b/src/data.json @@ -126,7 +126,7 @@ { "title": "My MinesSweeper! 😎", "github": "https://github.com/rulyotano/minesweeper", - "web": "https://webminesweeper.azurewebsites.net/mines-sweeper", + "web": "https://minesweeper.rulyotano.com/mines-sweeper", "contentParagraphs": [ "Just a fun project, but it is a good example of how to use ReactJs + Redux pattern. Also, I play it a lot when I'm bored." ], From 1c3c7428acb5320987f67583eb57375a2a06944b Mon Sep 17 00:00:00 2001 From: Raul Date: Fri, 11 Aug 2023 01:13:05 +0200 Subject: [PATCH 08/14] fix http --- src/data.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data.json b/src/data.json index 8b76a3f..71b8540 100644 --- a/src/data.json +++ b/src/data.json @@ -126,7 +126,7 @@ { "title": "My MinesSweeper! 😎", "github": "https://github.com/rulyotano/minesweeper", - "web": "https://minesweeper.rulyotano.com/mines-sweeper", + "web": "http://minesweeper.rulyotano.com/mines-sweeper", "contentParagraphs": [ "Just a fun project, but it is a good example of how to use ReactJs + Redux pattern. Also, I play it a lot when I'm bored." ], From 778331a516f3c72d66da473acc181381880728ed Mon Sep 17 00:00:00 2001 From: Raul Date: Sat, 12 Aug 2023 00:37:06 +0200 Subject: [PATCH 09/14] Update minesweeper to use https --- src/data.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data.json b/src/data.json index 71b8540..8b76a3f 100644 --- a/src/data.json +++ b/src/data.json @@ -126,7 +126,7 @@ { "title": "My MinesSweeper! 😎", "github": "https://github.com/rulyotano/minesweeper", - "web": "http://minesweeper.rulyotano.com/mines-sweeper", + "web": "https://minesweeper.rulyotano.com/mines-sweeper", "contentParagraphs": [ "Just a fun project, but it is a good example of how to use ReactJs + Redux pattern. Also, I play it a lot when I'm bored." ], From e5fb1eb9b25017c5cd05a1fa745944f9c6573131 Mon Sep 17 00:00:00 2001 From: Raul Date: Fri, 25 Aug 2023 09:32:25 +0200 Subject: [PATCH 10/14] Removed repeated shield --- pages/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/index.tsx b/pages/index.tsx index 4797f49..c46d269 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -135,7 +135,6 @@ export default function Index() { .NET C# Python - TypeScript Node.js Docker Docker Swarm From 27943af99a6014d7855558322e71f766166c3a4c Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 4 Oct 2023 13:59:16 +0200 Subject: [PATCH 11/14] Update data --- src/data.json | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/data.json b/src/data.json index 8b76a3f..bc4354a 100644 --- a/src/data.json +++ b/src/data.json @@ -35,43 +35,43 @@ ] }, { - "title": "Senior Software Developer", + "title": "Senior Software Engineer", "place": "Mimacom", "placeUrl": "https://mimacom.com/es", "image": "/img/mimacom-favicon.ico", "timePeriod": "2020/07 - 2021/03", "contentParagraphs": [ - "Worked as a Senior Software Developer for one of the company’s clients: Openbank. Mainly worked on frontend projects on ReactJs. Also, conducted many job interviews to new candidates that wanted to join the company." + "Client: Openbank. Mainly worked on frontend projects on ReactJs. Also, conducted many job interviews to new candidates that wanted to join the company." ] }, { - "title": "Full Stack Developer", + "title": "Full Stack Engineer", "place": "Consol Freight LLC", "placeUrl": "https://consolfreight.com", "image": "https://lh3.googleusercontent.com/pw/ACtC-3fTn39b_g3K6nCYsI4OkuEP_jBgkr4zLcOR_KATKLuwbZPk2YI0Irr1OBoDbRTbFCU6xt9PUMPnCNfpksJLMnD-Il5eFJ9Jd_0wAQy3Q37FEp1mUsdpgyZuGg2jR72V7ecUGSt9rq7l38AmqiZMHNnYGg", "timePeriod": "2018/04 - 2020/06", "contentParagraphs": [ - "Lead software developer for developing and maintaining the platform system. It was like a social network for moving maritime charges. The API system was made on ASP.NET MVC CORE with C# and with .NET tech in general. The front-end part was done using React.js tech." + "Creating and maintaining the platform system. It was like a social network for moving maritime charges. The API system was made on ASP.NET MVC CORE with C# and with .NET tech in general. The front-end part was done using React.js tech." ] }, { - "title": "Web Developer", + "title": "Web Engineer", "place": "Solinftec", "placeUrl": "https://solinftec.com", "image": "https://lh3.googleusercontent.com/pw/ACtC-3fYfddxp5HeZPvTQErQTWmvnHr7UKkF89bvyxN-_Rr5uXsWxfuTjL0a7R6XL8bxGb5_juCAOL9FINT_FvVm4VZadd-9xXKofHgLJGa2iEerbR2rr2GjhINqtRK0NC7alkjErrL3HuFbLj0sqxrb3_YsiQ", "timePeriod": "2016/08 - 2018/08", "contentParagraphs": [ - "Lead frontend Software Develop for creating the online system for monitoring the agriculture pieces of equipment. Need to show maps with area and movements, tracking of measured parameters, data analysis, data charts, tables, etc. Done using AngularJs, and ReactJs. The part of the maps was done with GoogleMaps and Mapbox." + "Creating the online system for monitoring the agriculture pieces of equipment. Needed to show maps with area and movements, tracking of measured parameters, data analysis, data charts, tables, etc. Done using AngularJs, and ReactJs. The part of the maps was done with GoogleMaps and Mapbox." ] }, { - "title": "Software Developer", + "title": "Software Engineer", "place": "Xmovo", "placeUrl": "https://www.linkedin.com/company/xmovo-group-inc/about", "image": "https://lh3.googleusercontent.com/pw/ACtC-3fU8evJuHGccK1xxYDcu1QBFtEW2oLb_nWLTFMRvhRbYSus9NtvpWembwrLb-cINr75dLmXTVAEMecv9hPOWlJFCibTbZ4EQnM_1xF5mAsm2HhcS-ixFM4tZQMNoNvnLO7OTaGsqsDTsYy73GsVTO9Tnw", "timePeriod": "2014/09 - 2016/08", "contentParagraphs": [ - "Web Developer for creating Xmovo, a social network for training and fitness. Was developed using .NET technologies: Asp.NET MVC 5, C#, Angular JS, and then React JS, Signal-R, DDD, SOLID principles, and others." + "Creating Xmovo, a social network for training and fitness. Was developed using .NET technologies: Asp.NET MVC 5, C#, Angular JS, and then React JS, Signal-R, DDD, SOLID principles, and others." ] }, { @@ -126,7 +126,7 @@ { "title": "My MinesSweeper! 😎", "github": "https://github.com/rulyotano/minesweeper", - "web": "https://minesweeper.rulyotano.com/mines-sweeper", + "web": "https://minesweeper.rulyotano.com", "contentParagraphs": [ "Just a fun project, but it is a good example of how to use ReactJs + Redux pattern. Also, I play it a lot when I'm bored." ], @@ -165,6 +165,14 @@ "Back then, Safari web browser had a similar panel and I wanted to have it in WPF." ], "image": "https://github.com/rulyotano/wpf-drag-animated-panel/raw/master/grag-animated-panel.gif?raw=true" + }, + { + "title": "Sample of Working Message Queue", + "github": "https://github.com/rulyotano/sample-queue-workers", + "contentParagraphs": [ + "Sample project to create a message queue to process long running tasks." + ], + "image": "https://raw.githubusercontent.com/rulyotano/sample-queue-workers/main/images/3_2_more_workers.png" } ], "articles": [ From 7e7d263a5861b2ffd2ebc41bd0d2fd910a7d7eaf Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 17 Oct 2023 17:27:26 +0200 Subject: [PATCH 12/14] Improve descriptions and add couple of projects --- pages/index.tsx | 6 +++--- src/data.json | 52 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index c46d269..5fe15c8 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -115,13 +115,13 @@ export default function Index() { - I am a passionate coder with expertise in web development and a strong focus on clean code, good practices, and solid principles. I have a deep love for coding, algorithms, and data structures, and I enjoy working with various web technologies. + I'm a passionate coder with expertise in web development, emphasizing clean code, good practices, and SOLID principles. I have a deep passion for coding, algorithms, data structures, and various web technologies. - I have a solid understanding of system design and architecture, enabling me to create scalable and efficient solutions. I am also enthusiastic about contributing to open-source libraries and helpers. + I like system design topics and would love to help to create scalable and efficient solutions. "I'm also enthusiastic about contributing to open-source projects, enhancing libraries, and assisting fellow developers. - Let's collaborate and build amazing software together! + I'm eager to collaborate and create outstanding software with you! Highlighted used Tech: diff --git a/src/data.json b/src/data.json index bc4354a..7dad268 100644 --- a/src/data.json +++ b/src/data.json @@ -31,17 +31,17 @@ "image": "https://lh3.googleusercontent.com/pw/ACtC-3eAdZYp96so-BMbxGty_qum7xEBApzC39b0q3MhLujo6_7-2acXmN-Uk9at4yzwacVdVFG99mM3D9BgZjqz0k0xP3Ytg_UR0lGkebzs-ATQaRJgEh9-EqC-v69EdVg8XzDAxqh5-StHFRKUioLIMRSGLw", "timePeriod": "2021/03 - actually", "contentParagraphs": [ - "Worked as part of my team Umbrella. DP has two main parts, one is the marketplace where patients search for doctors, and the other part is where the doctors manage their patients, patients’ episodes, and appointments. We worked in the doctor part, specifically patients and episodes. Among the challenges we faced, one interesting one was to take parts from the big monolith to new dedicated microservices." + "I worked as a member of the Umbrella team. DP had two main components: a patient-doctor marketplace and a platform for doctors to manage patients, episodes, and appointments. I primarily worked on the doctor's side, with a specific focus on managing patients, episodes, and related tasks. I encountered various challenges, including optimizing existing code to enhance throughput and reduce latency. I also took the initiative to create new micro-services from scratch. Throughout this experience, I acquired a wealth of new knowledge and skills." ] }, { - "title": "Senior Software Engineer", + "title": "Senior Software Engineer for Openbank", "place": "Mimacom", "placeUrl": "https://mimacom.com/es", "image": "/img/mimacom-favicon.ico", "timePeriod": "2020/07 - 2021/03", "contentParagraphs": [ - "Client: Openbank. Mainly worked on frontend projects on ReactJs. Also, conducted many job interviews to new candidates that wanted to join the company." + "I served as a Senior Software Developer at Openbank, a client of Mimacom. My role primarily focused on frontend development using React.js. The primary challenge was to develop a new on-boarding application while adhering to best practice standards and incorporating Openbank technologies.A portion of the application required integration into the mobile app, which presented an additional challenge. I also conducted numerous job interviews for candidates interested in joining Mimacom." ] }, { @@ -51,27 +51,28 @@ "image": "https://lh3.googleusercontent.com/pw/ACtC-3fTn39b_g3K6nCYsI4OkuEP_jBgkr4zLcOR_KATKLuwbZPk2YI0Irr1OBoDbRTbFCU6xt9PUMPnCNfpksJLMnD-Il5eFJ9Jd_0wAQy3Q37FEp1mUsdpgyZuGg2jR72V7ecUGSt9rq7l38AmqiZMHNnYGg", "timePeriod": "2018/04 - 2020/06", "contentParagraphs": [ - "Creating and maintaining the platform system. It was like a social network for moving maritime charges. The API system was made on ASP.NET MVC CORE with C# and with .NET tech in general. The front-end part was done using React.js tech." + "I served as a full-stack engineer to successfully complete and launch the ConsolFreight web application. The primary objective of this system was to facilitate the sale of cargo routes to individuals and businesses looking to ship their goods. One of the major challenges involved translating complex industry requirements into a coherent domain definition that could be implemented in the application. I utilized a combination of technologies, including Aspnet MVC, MVC Core, ReactJs/Redux, and also played a key role in setting up CI/CD pipelines using Azure." ] }, { - "title": "Web Engineer", + "title": "Lead Frontend Software Engineer", "place": "Solinftec", "placeUrl": "https://solinftec.com", "image": "https://lh3.googleusercontent.com/pw/ACtC-3fYfddxp5HeZPvTQErQTWmvnHr7UKkF89bvyxN-_Rr5uXsWxfuTjL0a7R6XL8bxGb5_juCAOL9FINT_FvVm4VZadd-9xXKofHgLJGa2iEerbR2rr2GjhINqtRK0NC7alkjErrL3HuFbLj0sqxrb3_YsiQ", "timePeriod": "2016/08 - 2018/08", "contentParagraphs": [ - "Creating the online system for monitoring the agriculture pieces of equipment. Needed to show maps with area and movements, tracking of measured parameters, data analysis, data charts, tables, etc. Done using AngularJs, and ReactJs. The part of the maps was done with GoogleMaps and Mapbox." + "Developed the web frontend system to display agriculture field data to users. The system displays maps showing the position and status of equipment. It also provides real-time weather condition information. The system sends alerts to users when specific parameters deviate from the expected range. Users can filter and manipulate the data. One of the key challenges was integrating various technologies, such as AngularJS and Google Maps. Additionally, we successfully migrated from Google Maps to Mapbox and from AngularJS to ReactJS over time." ] }, { - "title": "Software Engineer", + "title": "Fullstack Software Engineer", "place": "Xmovo", "placeUrl": "https://www.linkedin.com/company/xmovo-group-inc/about", "image": "https://lh3.googleusercontent.com/pw/ACtC-3fU8evJuHGccK1xxYDcu1QBFtEW2oLb_nWLTFMRvhRbYSus9NtvpWembwrLb-cINr75dLmXTVAEMecv9hPOWlJFCibTbZ4EQnM_1xF5mAsm2HhcS-ixFM4tZQMNoNvnLO7OTaGsqsDTsYy73GsVTO9Tnw", "timePeriod": "2014/09 - 2016/08", "contentParagraphs": [ - "Creating Xmovo, a social network for training and fitness. Was developed using .NET technologies: Asp.NET MVC 5, C#, Angular JS, and then React JS, Signal-R, DDD, SOLID principles, and others." + "I collaborated with the Xmovo team to develop a new social network website focused on training and fitness. This ambitious project featured a range of components, including a feeds section, notification system, chat functionality, e-commerce for training programs and memberships, live video training classes, and more. Unfortunately, the project was not successful, and the owners decided to close it.", + "Key Technologies: C#, ASP.NET MVC 5, Entity Framework 6, AngularJS, React.js, SignalR, Domain-Driven Design (DDD), SOLID principles, and more." ] }, { @@ -83,6 +84,18 @@ "contentParagraphs": [ "Develop and maintain all kind of software in the company. Mainly on .NET technologies." ] + }, + { + "title": "Freelancer and Previous jobs", + "place": "Many companies (Synotech AG, doiTTeam, vWorker, ...", + "timePeriod": "2010 - 2013", + "contentParagraphs": [ + "During my university years, I primarily worked as a freelance developer for various companies.", + "I developed numerous WPF applications and gained proficiency in best practices and design patterns, with MVVM being a prominent example, particularly in the context of WPF and Silverlight.", + "I collaborated with colleagues to establish the doiTTeam, an initiative focused on organizing our freelance work.", + "I successfully completed a couple of projects during my internship with a specific company I was assigned to.", + "During this period, I acquired valuable skills in real-world application development, primarily focusing on .NET technologies, including C#, WPF, Windows Forms, NHibernate, ActiveRecord, Entity Framework, various ORMs, and database systems like SQL Server and SQLite." + ] } ], "education": [ @@ -91,7 +104,12 @@ "place": "University of Havana", "placeUrl": "http://www.uh.cu", "image": "https://lh3.googleusercontent.com/pw/ACtC-3eU2fJDzygIqoFlfDqF1-MmM2MfyHQYMx6qnRv1hf07lbF-BtvJ-MTXdqMsJT7kdTQqur1wZYihHUJAhBYuI_zW67_tzJlUiVaXj_vhNiVYIIiVB75xL6ZyIDKorHn2_veH_77OG_wqDVP4Edwsq1Z71A", - "timePeriod": "2007/09 - 2013/05" + "timePeriod": "2007/09 - 2013/05", + "contentParagraphs": [ + "I graduated with a strong foundation in Computer Science, where I gained knowledge in a wide range of subjects.", + "My coursework covered fundamental topics such as mathematics, logic, and algebra, providing a solid grounding for my studies.", + "In addition, I delved into various Computer Science-related subjects, including programming, compilers, artificial intelligence, databases, networking, optimizations, and more." + ] } ], "projects": [ @@ -173,6 +191,22 @@ "Sample project to create a message queue to process long running tasks." ], "image": "https://raw.githubusercontent.com/rulyotano/sample-queue-workers/main/images/3_2_more_workers.png" + }, + { + "title": "Sample of Creating Servers in Sequence with ZooKeeper", + "github": "https://github.com/rulyotano/sample-sequence-server-zookeeper", + "contentParagraphs": [ + "The goal of this sample project is to be able to have many servers with a unique sequence number." + ], + "image": "https://i0.wp.com/datascientest.com/wp-content/uploads/2023/03/apache-zookeeper-datascientest.png?fit=1200%2C600&ssl=1" + }, + { + "title": "CV", + "github": "https://github.com/rulyotano/cv", + "contentParagraphs": [ + "This open-source project offers a LaTeX-based CV template that is designed for professional use." + ], + "image": "https://github.com/rulyotano/cv/blob/main/images/cv.png?raw=true" } ], "articles": [ From 91c7b1a42e281ebd527eabe0349109a1d5297450 Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 5 Dec 2023 12:44:09 +0100 Subject: [PATCH 13/14] Style fixing --- pages/index.tsx | 43 ++++++++++++++++++++++--------------- src/components/DataItem.tsx | 39 ++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 5fe15c8..431f205 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -123,26 +123,30 @@ export default function Index() { I'm eager to collaborate and create outstanding software with you! - - Highlighted used Tech: + - - ReactJS - AngularJS - Vue - JavaScript - TypeScript - .NET - C# - Python - Node.js - Docker - Docker Swarm - GitHub Actions - K8s + + +
+ ReactJS + AngularJS + Vue + JavaScript + TypeScript + .NET + C# + Python + Node.js + Docker + Docker Swarm + GitHub Actions + K8s +
+ + {settings.experience.map(it => ( ({ title: { - marginLeft: theme.spacing(2) + marginLeft: theme.spacing(2), + }, + techImages: { + '& > img': { + marginRight: theme.spacing(1) + } } })) \ No newline at end of file diff --git a/src/components/DataItem.tsx b/src/components/DataItem.tsx index 3742c2f..441272a 100644 --- a/src/components/DataItem.tsx +++ b/src/components/DataItem.tsx @@ -11,6 +11,7 @@ import Box from '@material-ui/core/Box'; import Divider from '@material-ui/core/Divider'; import Typography from '@material-ui/core/Typography'; import Collapse from '@material-ui/core/Collapse'; +import ImageIcon from '@material-ui/icons/Photo'; import ExpandButton from './ExpandButton'; import { getGoogleImageWithSize } from 'utils/googlePhotos'; @@ -25,14 +26,19 @@ export default function DataItem({ image = null, title = "", place = "", timePer - + + + {imageWithSize ? ( + + ) : } + + @@ -88,6 +94,12 @@ const Actions = ({ isExpanded, setIsExpanded }) => { ) } +const NoImage = ({}) => { + const classes = useStyles(); + + return +} + const useStyles = makeStyles((theme) => ({ root: { width: "100%", @@ -107,7 +119,14 @@ const useStyles = makeStyles((theme) => ({ margin: theme.spacing(2) }, paragraph: { - textIndent: theme.spacing(1), - textAlign: "justify" + // textIndent: theme.spacing(1), + textAlign: "justify", + marginTop: theme.spacing(2), + lineHeight: 1.2 + }, + noImage: { + width: 50, + height: 50, + margin: theme.spacing(2) } })) From 847a3b4303ee878e2f086decbc6be092abcbb694 Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 5 Dec 2023 16:04:51 +0100 Subject: [PATCH 14/14] Include minesweeper reference --- pages/index.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pages/index.tsx b/pages/index.tsx index 431f205..d5a19e6 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -21,6 +21,7 @@ import CodesignalIcon from "components/icons/CodesignalIcon"; import MediumIcon from "components/icons/MediumIcon"; import SectionItemReference from "components/SectionItemReference"; import DataItem from "components/DataItem"; +import MineIcon from "@material-ui/icons/Brightness5Outlined"; import settings from "data.json"; import gravatar from "gravatar.json"; @@ -109,6 +110,13 @@ export default function Index() { description="contact@rulyotano.com" />
+ + +