From f37c1c92aa7f4105926bc323c0fdfe8bd46f641e Mon Sep 17 00:00:00 2001 From: Shawn Becker Date: Mon, 1 Jan 2024 13:52:15 -0700 Subject: [PATCH] fixed monocolor issues, renamed ICON_TYPES and icon filenames --- .gitignore | 2 +- README.md | 6 +- index.html | 7 +- main.mjs | 216 +++++++----- modules/alerts.mjs | 5 +- .../css-colors.json => modules/css_colors.mjs | 55 ++- modules/monoColor.mjs | 87 ++++- modules/utils.mjs | 318 ++++++++++++++---- scratch.html | 23 +- ...e-16-black.png => icons8-img-16-black.png} | Bin ...e-16-white.png => icons8-img-16-white.png} | Bin ...y-16-black.ico => icons8-url-16-black.ico} | Bin ...y-16-black.png => icons8-url-16-black.png} | Bin ...y-16-white.ico => icons8-url-16-white.ico} | Bin ...y-16-white.png => icons8-url-16-white.png} | Bin .../jobs/convert-jobs-xslx-to-mjs.sh | 2 +- static_content/jobs/csv2json.py | 2 +- static_content/jobs/jobs.csv | 89 +++++ static_content/jobs/jobs.json | 1 + static_content/jobs/jobs.mjs | 250 +++++++++++++- static_content/jobs/jobs.xlsx | Bin 20757 -> 19624 bytes static_content/jobs/~$jobs.xlsx | Bin 0 -> 165 bytes 22 files changed, 876 insertions(+), 187 deletions(-) rename static_content/fragments/css-colors.json => modules/css_colors.mjs (71%) rename static_content/icons/{icons8-image-16-black.png => icons8-img-16-black.png} (100%) rename static_content/icons/{icons8-image-16-white.png => icons8-img-16-white.png} (100%) rename static_content/icons/{icons8-geography-16-black.ico => icons8-url-16-black.ico} (100%) rename static_content/icons/{icons8-geography-16-black.png => icons8-url-16-black.png} (100%) rename static_content/icons/{icons8-geography-16-white.ico => icons8-url-16-white.ico} (100%) rename static_content/icons/{icons8-geography-16-white.png => icons8-url-16-white.png} (100%) create mode 100644 static_content/jobs/jobs.csv create mode 100644 static_content/jobs/jobs.json create mode 100644 static_content/jobs/~$jobs.xlsx diff --git a/.gitignore b/.gitignore index cffeb5c..12a22a5 100644 --- a/.gitignore +++ b/.gitignore @@ -92,7 +92,7 @@ lerna-debug.log **/.DS_Store Thumbs.db **/venv -**/images/* +**/imgs/* # Large .mov files *.mov \ No newline at end of file diff --git a/README.md b/README.md index 0a063a8..2fc67c7 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The static 'flock-of-postcards' website has been upgraded to be a webapp that us ### Planned features: - Need to ease focal point to bullseye when any cardDiv is selected (or clicked?) - Need to add stamp icons to post cards -- Click on post card to see full-size image in right-side panel +- Click on post card to see full-size img in right-side panel - Render bizcards as 3D blocks with rounded corners - Rotate 3D bizcard blocks during transitions - Toggle debug panel visiblilty with button or key @@ -103,7 +103,7 @@ The static 'flock-of-postcards' website has been upgraded to be a webapp that us #### Features added: -- scripted process to convert WordPress media dump xml file into a javascript file of image paths of resized local image files (not included in github) for html inclusion. +- scripted process to convert WordPress media dump xml file into a javascript file of img paths of resized local img files (not included in github) for html inclusion. - scripted process to convert excel jobs.xlsx spreadsheet file (included in github) into a javascript file of job objects for html inclusion. - right side now has fixed header and footer and an auto-scolling content. - click on a any postcard or underlying buisness card to add a new deleteble line item to the right column. @@ -142,7 +142,7 @@ The static 'flock-of-postcards' website has been upgraded to be a webapp that us #### Features added: - randomized div sizes, locations, and z-index - z-index affects opacity and brightness -- autogenerated images from web +- autogenerated imgs from web - vertical stack of divs moved to canvas-container center on load and resize - vertical scrollbar - fat middle line for diagnositcs diff --git a/index.html b/index.html index 9ed3598..94427b3 100644 --- a/index.html +++ b/index.html @@ -16,11 +16,12 @@ - + - + +
@@ -43,7 +44,7 @@

Shawn Becker

Data Engineer / Software Developer

-

sbecker@alum.mit.edu • 857-891-0896
https://linkedin.com/in/shawnbecker • Lehi - Utah, USA

+

sbecker@alum.mit.edu • 857-891-0896
https://linkedin.com/in/shawnbecker • Lehi - Utah, USA

diff --git a/main.mjs b/main.mjs index 77b427c..2e9aa1b 100644 --- a/main.mjs +++ b/main.mjs @@ -3,7 +3,6 @@ 'use strict'; import * as utils from './modules/utils.mjs'; -import * as alerts from './modules/alerts.mjs'; import * as timeline from './modules/timeline.mjs'; import * as focalPoint from './modules/focal_point.mjs'; import * as monoColor from './modules/monoColor.mjs'; @@ -270,8 +269,14 @@ function createBizcardDivs() { bizcardDiv.style.zIndex = zIndexStr; canvas.appendChild(bizcardDiv); - - bizcardDiv.setAttribute("endDate", utils.getIsoDateString(endDate)); + bizcardDiv.dataset.employer = employer; + bizcardDiv.dataset.cardDivIds = []; + try { + console.log(`startDate:[${endDate}]`); + bizcardDiv.setAttribute("endDate", utils.getIsoDateString(endDate)); + } catch (e) { + console.error(e); + } bizcardDiv.setAttribute("startDate", utils.getIsoDateString(startDate)); // save the original center @@ -322,6 +327,7 @@ function createBizcardDivs() { bizcardDiv.addEventListener("mouseenter", handleCardDivMouseEnter); bizcardDiv.addEventListener("mouseleave", handleCardDivMouseLeave); + utils.validateIsCardDivOrBizcardDiv(bizcardDiv); addCardDivClickListener(bizcardDiv); // does not select self // does not scroll self into view @@ -329,23 +335,6 @@ function createBizcardDivs() { } } -// function handleTagLinkClick(event) { -// // console.assert(event != null); -// var tag_link = event.target; -// // console.assert(tag_link != null); -// var targetCardDivId = tag_link.getAttribute("targetCardDivId"); -// // console.assert(targetCardDivId != null); -// var targetCardDiv = document.getElementById(targetCardDivId); -// // console.assert(targetCardDiv != null); -// if (targetCardDiv) { -// // console.log(`handleTagLinkClick: ${targetCardDivId}`); -// selectTheCardDiv(targetCardDiv, true); -// scrollElementIntoView(targetCardDiv); -// if ( theSelectedCardDiv !== null && theSelectedCardDiv.id !== targetCardDiv.id ) { -// console.log(`handleTagLinkClick: ${targetCardDivId} not selected`); -// } -// } -// } // -------------------------------------- // tag_link globals @@ -399,21 +388,25 @@ function process_bizcard_description_HTML(bizcardDiv, description_HTML) { return [processed_bizcard_description_HTML, bizcardTagLinks]; } -function createUrlAnchorTag(url, savedColor, savedBackgroundColor) { +function createUrlAnchorTag(url, savedColor) { let iconColor = monoColor.getIconColor(savedColor); - let html = ``; + let iconType = "url"; + let html = ``; return html; } -function createImgAnchorTag(img, savedColor, savedBackgroundColor) { +function createImgAnchorTag(img, savedColor) { let iconColor = monoColor.getIconColor(savedColor); - let html = ``; + let iconType = "img"; + let html = ``; return html; } -function createBackAnchorTag(bizcard_id, savedColor, savedBackgroundColor) { +function createBackAnchorTag(bizcard_id, savedColor, isMonocolorSensitive=true) { let iconColor = monoColor.getIconColor(savedColor); - let html = ``; + let iconType = "back"; + let monoColorSensitiveClass = isMonocolorSensitive ? "mono-color-sensitive" : ''; + let html = ``; return html; } @@ -460,7 +453,6 @@ function process_bizcard_description_item(bizcardDiv, inputString) { const url = tag_link.url ? tag_link.url : ''; var savedColor = bizcardDiv.getAttribute('saved-color') || ''; - var savedBackgroundColor = bizcardDiv.getAttribute('saved-background-color') || ''; if (typeof savedColor === 'undefined' || savedColor === null || savedColor === '') { throw new Error(`bizcardDiv:${bizcardDiv.id} must have a saved-color attribute`); @@ -473,21 +465,22 @@ function process_bizcard_description_item(bizcardDiv, inputString) { htmlElementStr = `${text}`; var line2 = ''; - // If img is defined, add an anchor tag wrapping the local image.png + // If img is defined, add an anchor tag wrapping the local img.png if (img) { - line2 += createImgAnchorTag(img, savedColor, savedBackgroundColor); + line2 += createImgAnchorTag(img, savedColor); } // If url is defined, add an anchor tag wrapping the local geo.png if (url) { - line2 += createUrlAnchorTag(url, savedColor, savedBackgroundColor); + line2 += createUrlAnchorTag(url, savedColor); } - line2 += createBackAnchorTag(bizcardDiv.id, savedColor, savedBackgroundColor); + // always add the initial backAnchorTag + line2 += createBackAnchorTag(bizcardDiv.id, savedColor); htmlElementStr += '
' + line2; if ( htmlElementStr.includes('undefined')) { - throw new Error(`htmlElementStr:${htmlElementStr} must not have an undefined attribute`); + throw new Error(`htmlElementStr:${htmlElementStr} must not have any undefined values`); } } tag_link.html = htmlElementStr; @@ -496,7 +489,7 @@ function process_bizcard_description_item(bizcardDiv, inputString) { setCardDivIdOfTagLink(bizcardDiv, tag_link); // create a tag_link span element with the targetCardDivId attribute and the htmlElementStr as its innerHTML - let htmlSpanElementStr = `${htmlElementStr}`; + let htmlSpanElementStr = `${htmlElementStr}`; // reconstruct the original pattern let originalPattern = `[${text}]`; @@ -526,16 +519,20 @@ function setCardDivIdOfTagLink(bizcardDiv, tag_link) { cardDiv = createCardDiv(bizcardDiv, tag_link); } tag_link.cardDivId = cardDiv.id; + let comma = (bizcardDiv.dataset.cardDivIds.length > 0) ? ',' : ''; + bizcardDiv.dataset.cardDivIds += comma + cardDiv.id; } // add a click listener to the given icon element function addIconClickListener(icon) { icon.addEventListener("click", (event) => { const iconElement = event.target; + event.stopPropagation(); + if (iconElement) { const iconType = iconElement.dataset.icontype; switch (iconType) { - case 'geography': { + case 'url': { const url = iconElement.dataset.url; // from data-url if (url) { console.log(`iconElement iconType:${iconType} click: ${url}`); @@ -545,8 +542,8 @@ function addIconClickListener(icon) { } break; } - case 'image': { - const img = iconElement.dataset.image; // from data-image + case 'img': { + const img = iconElement.dataset.img; // from data-img if (img) { console.log(`iconElement iconType:${iconType} click: ${img}`); window.open(img, "_blank"); @@ -588,9 +585,9 @@ function getBizcardDivDays(bizcardDiv) { const endMillis = getBizcardDivEndDate(bizcardDiv).getTime(); const startMillis = getBizcardDivStartDate(bizcardDiv).getTime(); const bizcardMillis = endMillis - startMillis; - console.log(`bizcardDiv.id:${bizcardDiv.id} bizcardMillis:${bizcardMillis}`); + // console.log(`bizcardDiv.id:${bizcardDiv.id} bizcardMillis:${bizcardMillis}`); const bizcardDivDays = bizcardMillis / (1000 * 60 * 60 * 24); - console.log(`bizcardDiv.id:${bizcardDiv.id} bizcardDivDays:${bizcardDivDays}`); + // console.log(`bizcardDiv.id:${bizcardDiv.id} bizcardDivDays:${bizcardDivDays}`); return parseInt(bizcardDivDays); } @@ -612,8 +609,7 @@ function findCardDiv(bizcardDiv, tag_link) { if ( numFound === 0 ) { // default the colors from the bizcardDiv var savedColor = cardDiv.getAttribute('saved-color') || ''; - var savedBackgroundColor = cardDiv.getAttribute('saved-background-color') || ''; - let newBackAnchorTag = createBackAnchorTag(bizcardDiv.id, savedColor, savedBackgroundColor); + let newBackAnchorTag = createBackAnchorTag(bizcardDiv.id, savedColor, false); let spanTagLink = cardDiv.querySelector('span.tag-link'); if ( spanTagLink ) { spanTagLink.innerHTML += newBackAnchorTag; @@ -688,7 +684,7 @@ function getNextCardDivId() { return nextCardDivId; } -var prev_z = null; // to track the previous z value +var prev_z = null; // to track the previous z value // adds a new cardDivs to #canvas // default center x to zero and center y to @@ -702,6 +698,8 @@ function createCardDiv(bizcardDiv, tag_link) { var cardDivId = getNextCardDivId(); var cardDiv = document.createElement('div'); cardDiv.classList.add("card-div"); + utils.validateIsCardDivOrBizcardDiv(cardDiv); + cardDiv.tag_link = tag_link; cardDiv.id = cardDivId; canvas.appendChild(cardDiv); @@ -756,9 +754,10 @@ function createCardDiv(bizcardDiv, tag_link) { // the tag_link is used to define the contents of this cardDiv const spanId = `tag_link-${cardDivId}`; + let savedColor = cardDiv.getAttribute("saved-color"); // define the innerHTML when cardDiv is added to #canvas - cardDiv.innerHTML = `${tag_link.html}`; + cardDiv.innerHTML = `${tag_link.html}`; const spanElement = document.getElementById(spanId); if (spanElement) { @@ -806,6 +805,7 @@ function createCardDiv(bizcardDiv, tag_link) { cardDiv.addEventListener("mouseenter", handleCardDivMouseEnter); cardDiv.addEventListener("mouseleave", handleCardDivMouseLeave); + utils.validateIsCardDivOrBizcardDiv(cardDiv); addCardDivClickListener(cardDiv); // does not select self // does not scroll self into view @@ -816,16 +816,68 @@ function createCardDiv(bizcardDiv, tag_link) { cardDiv.setAttribute("tagLinkUrl", tag_link[ "url" ]); cardDiv.setAttribute("tagLinkImg", tag_link[ "img" ]); - // cardDiv line items are never mono-color-sensitive + // all elements of cardDiv are not mono-color-sensitive let monocolorElements = Array.from(cardDiv.getElementsByClassName("mono-color-sensitive")); - for (let i = 0; i < monocolorElements.length; i++) { - let monocolorElement = monocolorElements[i]; + for (let monocolorElement of monocolorElements) { monocolorElement.classList.remove("mono-color-sensitive"); } return cardDiv; } +// write the exmployer of each bizcardDiv and the ext of each of its cardDivs +export function logAllBizcardDivs() { + let allBizcardDivs = document.getElementsByClassName("bizcard-div"); + var log = ""; + console.log('---------------------------------------------------'); + for (let bizcardDiv of allBizcardDivs) { + let employer = bizcardDiv.dataset.employer; + if (employer === undefined || employer === null) { + continue; + } + let cardDivIds = bizcardDiv.dataset.cardDivIds; + if ( cardDivIds.length > 0 ) { + for (let cardDivId of cardDivIds.split(',')) { + let cardDiv = document.getElementById(cardDivId); + if (cardDiv === null) { + console.log(`No element with id cardDivId:${cardDivId}`); + continue; + } + if ( cardDiv.dataset.bizcardDivMonths < 4) { + continue; + } + let cardDivText = cardDiv.getAttribute('tagLinkText'); + if ( cardDivText === undefined || cardDivText == null ) { + continue; + } + if ( cardDivText.includes('“') ) { + continue; + } + let ignores = [ + "Massachusetts Institute of Technology", + "Trimble Mobile Solutions", + "OneCall", + "HomePortfolio.com", + "Brigham Young University", + "four patents" + ]; + if ( ignores.includes(cardDivText) ) { + continue; + } + if ( employer.includes(cardDivText) ) { + continue; + } + if ( cardDivText.includes(employer) ) { + continue; + } + log += `"${employer}", "${cardDivText}"\n`; + } + } + } + console.log(log); + console.log('---------------------------------------------------'); +} + function copyHexColorAttributes(dstDiv, srcDiv, attrs) { // console.assert(dstDiv != null && srcDiv != null && attrs != null); for (var i = 0; i < attrs.length; i++) { @@ -1297,8 +1349,8 @@ function createStyleArray(obj, prefix) { let array = []; var RGB; if (prefix) { // use div.getAttribute - array = array.concat(utils.get_RGB_from_ColorStr(obj.getAttribute(`${prefix}-color`))); - array = array.concat(utils.get_RGB_from_ColorStr(obj.getAttribute(`${prefix}-background-color`))); + array = array.concat(utils.get_RGB_from_AnyStr(obj.getAttribute(`${prefix}-color`))); + array = array.concat(utils.get_RGB_from_AnyStr(obj.getAttribute(`${prefix}-background-color`))); if ( !isCardDivLineItem(obj) ) { // positionals var left = parseInt(obj.getAttribute(`${prefix}-left`)); array.push(left); @@ -1309,8 +1361,8 @@ function createStyleArray(obj, prefix) { array = array.concat([0,0,0]); } } else { // use div or div.style - array = array.concat(utils.get_RGB_from_ColorStr(obj.style.color)); - array = array.concat(utils.get_RGB_from_ColorStr(obj.style.backgroundColor)); + array = array.concat(utils.get_RGB_from_AnyStr(obj.style.color)); + array = array.concat(utils.get_RGB_from_AnyStr(obj.style.backgroundColor)); if ( !isCardDivLineItem(obj) ) { // positionals var left = obj.offsetLeft; array.push(left); @@ -1348,11 +1400,11 @@ function applyStyleArray(obj, styleArray) { // utils.validateIsElement(obj); // utils.validateIsStyleArray(styleArray); var rgbStr; - rgbStr = utils.get_rgbStr_from_RGB(styleArray.slice(0,3)); + rgbStr = utils.get_RgbStr_from_RGB(styleArray.slice(0,3)); obj.style.color = rgbStr; console.assert(obj.style.color === rgbStr); - rgbStr = utils.get_rgbStr_from_RGB(styleArray.slice(3,6)); + rgbStr = utils.get_RgbStr_from_RGB(styleArray.slice(3,6)); obj.style.backgroundColor = rgbStr; console.assert(obj.style.backgroundColor === rgbStr); @@ -1421,7 +1473,10 @@ function findNearestAncestorWithClassName(element, className) { function selectTheCardDiv(cardDiv, selectTheCardDivLineItemFlag=false) { if ( cardDiv == null ) return; - // utils.validateIsCardDivOrBizcardDiv(cardDiv); + if( !utils.isCardDivOrBizcardDiv(cardDiv) ) { + console.warn(`selectTheCardDiv ignoring invalid argument: ${cardDiv}`); + return; + } // utils.validateIsBoolean(selectTheCardDivLineItemFlag); // click on selected to deselect @@ -1479,10 +1534,11 @@ function deselectTheSelectedCardDiv(deselectTheSelectedCardDivLineItemFlag=false // handle mouse click event for any div element with // cardClass "card-div" or "bizcard-div". function addCardDivClickListener(cardDiv) { + utils.validateIsCardDivOrBizcardDiv(cardDiv); cardDiv.addEventListener("click", function (event) { - + let thisCardDiv = event.target; // select the cardDiv and its cardDivLineItem - selectTheCardDiv(cardDiv, true); + selectTheCardDiv(thisCardDiv, true); event.stopPropagation(); }) @@ -1600,6 +1656,7 @@ function addCardDivLineItem(targetCardDivId) { cardDivLineItemContent.classList.add("mono-color-sensitive"); cardDivLineItemContent.style.backgroundColor = 'transparent'; cardDivLineItemContent.style.color = targetCardDiv.getAttribute("saved-color") || ""; + cardDivLineItemContent.dataset.savedColor = targetCardDiv.getAttribute("saved-color") || ""; // set right column var cardDivLineItemRightColumn = document.createElement('div') @@ -1607,6 +1664,7 @@ function addCardDivLineItem(targetCardDivId) { cardDivLineItemRightColumn.classList.add("mono-color-sensitive"); cardDivLineItemRightColumn.style.backgroundColor = 'transparent'; cardDivLineItemRightColumn.style.color = targetCardDiv.getAttribute("saved-color") || ""; + cardDivLineItemRightColumn.dataset.savedColor = targetCardDiv.getAttribute("saved-color") || ""; // start with the innerHTML of the targetCardDiv var targetInnerHTML = targetCardDiv.innerHTML; @@ -1664,7 +1722,7 @@ function addCardDivLineItem(targetCardDivId) { } // find all iconElemens of this cardDivLineItemContent and make - // them mono-color-sensitive and give them onclick listeners. + // each mono-color-sensitive and give each an onclick listeners. // // However, delete any back-icons if the targetCardDiv is a bizcardDiv // @@ -1675,14 +1733,20 @@ function addCardDivLineItem(targetCardDivId) { let iconElements = cardDivLineItemContent.getElementsByClassName("icon"); for (let i = iconElements.length - 1; i >= 0; i--) { let iconElement = iconElements[i]; + if ( !iconElement.classList.contains('mono-color-sensitive') ) { + iconElement.classList.add('mono-color-sensitive'); + } let iconType = iconElement.dataset.icontype; if (deleteBackIcons && iconType === "back") { iconElement.parentNode.removeChild(iconElement); } else { addIconClickListener(iconElement); - iconElement.classList.add("mono-color-sensitive"); } } + // finish up by applying monocolor rules to the cardDivLineItem's mono-color-sensitive child elements + for ( let element of cardDivLineItem.getElementsByClassName("mono-color-sensitive") ) { + monoColor.applyMonoColorToElement(element); + } } else { // console.log(`returning preexisting cardDivLineItem for targetCardDivId:${targetCardDivId}`); cardDivLineItem = existingCardDivLineItem @@ -1892,37 +1956,6 @@ function easeFocalPointToBullsEye() { focalPoint.easeFocalPointTo(bullsEyeX, bullsEyeY); } -// function debugFocalPoint() { -// if ( debugFocalPointElement != null ) { -// var html = ""; -// if (isMouseOverCanvasContainer && mouseX && mouseY) -// html += `mouse in canvas [${mouseX},${mouseY}]
`; -// else -// html += "mouse not in canvas
"; - -// html += `bullsEye:[${bullsEyeX},${bullsEyeY}]
`; -// html += `focalPoint:[${focalPointX},${focalPointY}]
`; -// const { parallaxX, parallaxY } = getParallax(); -// html += `parallax:[${parallaxX},${parallaxY}]
`; - -// var time = (new Date()).getTime(); -// html += `time:${time}
`; - -// debugFocalPointElement.innerHTML = html; -// } -// } - -// function debugTheSelectedCardDivId() { -// if ( debugTheSelectedCardDivIdElement != null ) { -// var html = ""; -// var theSelectedCardDivIdStr = theSelectedCardDiv == null ? 'null' : `${theSelectedCardDiv.id}`; -// var theSelectedCardDivLineItemIdStr = theSelectedCardDivLineItem == null ? 'null' : `${theSelectedCardDivLineItem.id}`; -// html += `theSelectedCardDivIdStr:${theSelectedCardDivIdStr}
`; -// html += `theSelectedCardDivLineItemIdStr:${theSelectedCardDivLineItemIdStr}
`; -// debugTheSelectedCardDivIdElement.innerHTML = html; -// } -// } - // return the min and max years over the list of jobs function getMinMaxTimelineYears(jobs) { var minYear = 10000; @@ -2198,6 +2231,8 @@ export function addAllIconClickListeners() { export function addCardDivMonths(cardDiv, cardDivLineItemContent) { const days = cardDiv.dataset.bizcardDivDays; const months = Math.round(days * 12.0 / 365.25); + cardDiv.dataset.bizcardDivMonths = months; + cardDiv.dataset.bizcardDivYears = 0; let spanElement = cardDivLineItemContent.querySelector("span.tag-link"); if( spanElement ) { if ( months <= 12 ) { @@ -2207,6 +2242,7 @@ export function addCardDivMonths(cardDiv, cardDivLineItemContent) { const years = Math.round(months / 12.0); const units = years == 1 ? "year" : "years"; spanElement.innerHTML += `
(${years} ${units} experience)`; + cardDiv.dataset.bizcardDivYears = years; } } else { console.error(`no spanElement found for cardDiv:${cardDiv.id}`); @@ -2237,3 +2273,9 @@ addCanvasContainerEventListener('scroll', handleCanvasContainerScroll); addCanvasContainerEventListener('click', handleCanvasContainerMouseClick); +export function onCloseWelcomeAlert() { + selectAllBizcards(); + addAllIconClickListeners(); + logAllBizcardDivs(); + utils.testColorFunctions(); +} diff --git a/modules/alerts.mjs b/modules/alerts.mjs index ee029e0..30555b2 100644 --- a/modules/alerts.mjs +++ b/modules/alerts.mjs @@ -1,6 +1,6 @@ // @ts-nocheck -import { addAllIconClickListeners, selectAllBizcards } from '../main.mjs'; +import { onCloseWelcomeAlert } from '../main.mjs'; const overlay = document.getElementById('overlay'); const welcomeAlert = document.getElementById('welcomeAlert'); @@ -24,8 +24,7 @@ export function closeWelcomeAlert(event) { overlay.style.display = 'none'; welcomeAlert.setAttribute('aria-hidden', 'true'); - selectAllBizcards(); - addAllIconClickListeners(); + onCloseWelcomeAlert(); } // Event listener for overlay click diff --git a/static_content/fragments/css-colors.json b/modules/css_colors.mjs similarity index 71% rename from static_content/fragments/css-colors.json rename to modules/css_colors.mjs index 0c20ea4..5f5b6bf 100644 --- a/static_content/fragments/css-colors.json +++ b/modules/css_colors.mjs @@ -1,4 +1,6 @@ -{ +import * as utils from './utils.mjs'; + +const CSS_COLORS = { "AliceBlue": "#F0F8FF", "AntiqueWhite": "#FAEBD7", "Aqua": "#00FFFF", @@ -140,5 +142,52 @@ "WhiteSmoke": "#F5F5F5", "Yellow": "#FFFF00", "YellowGreen": "#9ACD32" - } - \ No newline at end of file +}; + +const LOWERCASE_CSS_COLORS = _getLowerCaseCssColors(); + +function _getLowerCaseCssColors() { + let lowerCaseColors = {}; + for (let color in CSS_COLORS) { + lowerCaseColors[color.toLowerCase()] = CSS_COLORS[color]; + } + return lowerCaseColors; +} + +export function get_HEX_from_CssColor(cssColor, verbose=false) { + if ( utils.isString(cssColor) ) { + let color = cssColor.toLowerCase(); + let colors = LOWERCASE_CSS_COLORS; + if ( color in colors ) { + let HEX = colors[color]; + if ( utils.isHexColorString(HEX)) { + return HEX; + } + if ( verbose ) + console.trace(`cssColor:[${cssColor}] found HEX:[${HEX}] but it's not a valid hexColorString`); + return null; + } + if( verbose ) + console.trace(`cssColor:[${cssColor}] no matching hexColorString found`); + return null; + } + if( verbose ) + console.trace(`cssColor:[${cssColor}] is not a valid string`); + return null; +} + +export function get_CssColor_from_HEX(HEX, verbose=false) { + if ( utils.isHexColorString(HEX) ) { + for (let color in LOWERCASE_CSS_COLORS) { + if (LOWERCASE_CSS_COLORS[color] === HEX) { + return color; + } + } + if( verbose ) + console.trace(`HEX:[${HEX}] no matching cssColor found`); + return null; + } + if( verbose ) + console.trace(`HEX:[${HEX}] is not a valid hexColorString`); + return null; +} \ No newline at end of file diff --git a/modules/monoColor.mjs b/modules/monoColor.mjs index 576b8c7..58db81a 100644 --- a/modules/monoColor.mjs +++ b/modules/monoColor.mjs @@ -6,16 +6,19 @@ var isMonoColor = false; const monoColor = "black"; const monoBackgroundColor = "lightgrey"; -export const ICON_TYPES = ['back', 'geometry', 'image']; +export const ICON_TYPES = ['back', 'url', 'img']; export const ICON_COLORS = ['black', 'white']; export function getIconColor(color) { - if (color in ICON_COLORS) { - return color; + if ((typeof color === undefined) || (color == null) || (color == "")) { + throw new Error(`getIconColor color:${color} is undefined`); } color = color.toUpperCase(); - let RGB = utils.get_RGB_from_ColorStr(color); + let RGB = utils.get_RGB_from_AnyStr(color); let iconColor = (RGB[0] + RGB[1] + RGB[2] > 382) ? 'white' : 'black'; + if ( !ICON_COLORS.includes(iconColor) ) { + throw new Error(`getIconColor color:${color} iconColor:${iconColor} not included by ${ICON_COLORS}\n`); + } return iconColor; } @@ -37,17 +40,59 @@ export function toggleMonoColor() { return isMonoColor; } -export function setIconToColor(iconElement, iconColor) { - let iconType = iconElement.dataset.iconType; - if( !(iconType in ICON_TYPES) ) { - console.trace(`iconElement:${iconElement} has illegal iconType:${iconType}`); +function getIconElementType(iconElement) { + let iconType = iconElement.dataset.icontype || iconElement.getAttribute('icon-type'); + if( typeof iconType ==='undefined' || iconType === null || iconType === "") { + if ( iconElement.classList.contains('back-icon') ) { + return 'back'; + } else if ( iconElement.classList.contains('url-icon') ) { + return 'url'; + } else if ( iconElement.classList.contains('img-icon') ) { + return 'img'; + } else { + var err = `getIconElementType iconElement:${iconElement} has no icon-type dataset or attribute\n`; + err += `getIconElementType iconElement.dataset:${utils.getDatasetAsString(iconElement)}\n`; + err += `getIconElementType iconElement.attributes:${utils.getAttributesAsString(iconElement)}\n`; + throw new Error(err); + } + } + if ( ICON_TYPES.includes(iconType) ) { + return iconType; + } else { + var err = `getIconElementType iconElement:${iconElement} iconType:${iconType} not included in ${ICON_TYPES}`; + throw new Error(err); } - if ( !(iconColor in ICON_COLORS) ) { - console.trace(`iconElement:${iconElement} has illegal iconColor:${iconColor}`); +} + +export function setIconToColor(iconElement, theIconColor) { + let iconType = getIconElementType(iconElement); + let iconColor = getIconColor(theIconColor); + if( !ICON_TYPES.includes(iconType) ) { + var err = `setIconToColor iconElement:${iconElement} has illegal iconType:[${iconType}] not included by ${ICON_TYPES}\n`; + err += `setIconToColor iconElement.dataset:${utils.getDatasetAsString(iconElement)}\n`; + err += `setIconToColor iconElement.attributes:${utils.getAttributesAsString(iconElement)}\n`; + throw new Error(err); + } + if ( !ICON_COLORS.includes(iconColor) ) { + var err = `setIconToColor iconElement:${iconElement} has illegal iconColor:[${iconColor}] not included by ${ICON_COLORS}\n`; + err += `setIconToColor iconElement.dataset:${utils.getDatasetAsString(iconElement)}\n`; + err += `setIconToColor iconElement.attributes:${utils.getAttributesAsString(iconElement)}\n`; + throw new Error(err); + } + // in colorMode + if ( !isMonoColor ) { + let savedColor = iconElement.dataset.savedColor; + if (typeof savedColor === undefined || savedColor == null || savedColor == '' ) { + var err = `setIconColor iconElement:${iconElement} savedColor is undefined`; + throw new Error(err); + } + if ( savedColor != iconColor ) { + var err = `setIconColor iconElement:${iconElement} in colorMode given iconColor:${iconColor} when savedColor:${savedColor}`; + throw new Error(err); + } } iconElement.src = 'static_content/icons/icons8-' + iconType + '-16-' + iconColor + '.png'; let bizcardId = iconElement.dataset.bizcardId; - console.log(`setIconToColor: iconType:${iconType} iconColor:${iconColor} bizcardId:${bizcardId}`); } export function applyMonoColorToElement(monoColorElement) { @@ -59,18 +104,24 @@ export function applyMonoColorToElement(monoColorElement) { setIconToColor(monoColorElement, monoColor); } } else { + // in colorMode // retrieve the saved colors from the dataset - let savedColor = monoColorElement.dataset.savedcolor; + let savedColor = monoColorElement.dataset.savedColor; if( typeof savedColor ==='undefined' || savedColor === null || savedColor === "") { - throw new Error(`monoColorElement:${monoColorElement} must have a data-saved-color attribute`); - } - let savedBackgroundColor = monoColorElement.dataset.savedbackgroundcolor; - if( typeof savedBackgroundColor ==='undefined' || savedBackgroundColor === null || savedBackgroundColor === "") { - throw new Error(`monoColorElement:${monoColorElement} must have a data-saved-background-color attribute`); + var err = `applyMonoColorToElement monoColorElement must have a saved-color data or attribute\n`; + err += `applyMonoColorToElement savedColor:[${savedColor}]\n`; + err += `applyMonoColorToElement isMonoColor:${isMonoColor}\n`; + err += `applyMonoColorToElement monoColorElement.dataset.savedColor:${monoColorElement.dataset.savedColor}\n`; + err += `applyMonoColorToElement monoColorElement.getAttribute('saved-color'):${monoColorElement.getAttribute('saved-color')}\n`; + err += `applyMonoColorToElement monoColorElement.dataset:${utils.getDatasetAsString(monoColorElement)}\n`; + err += `applyMonoColorToElement monoColorElement.attributes:${utils.getAttributesAsString(monoColorElement)}\n`; + err += `applyMonoColorToElement monoColorElement.tagName:${monoColorElement.tagName}\n`; + err += `applyMonoColorToElement monoColorElement.classList:${monoColorElement.classList}\n`; + throw new Error(err); } // restore the saved colors monoColorElement.style.color = savedColor; - monoColorElement.style.backgroundColor = savedBackgroundColor; + monoColorElement.style.backgroundColor = 'transparent'; if ( monoColorElement.classList.contains("icon") ) { setIconToColor(monoColorElement, savedColor); } diff --git a/modules/utils.mjs b/modules/utils.mjs index 1436ebe..e248d11 100644 --- a/modules/utils.mjs +++ b/modules/utils.mjs @@ -1,8 +1,31 @@ // @ts-check +import * as css_colors from './css_colors.mjs'; + // -------------------------------------- // Utility export functions +const EPSILON = 1.0; + +export function isHexColorString(hexColorStr) { // enforces uppercase hex string only + return isString(hexColorStr) && /^#[0-9A-F]{6}$/.test(hexColorStr); +} +export function validateHexColorString(hexColorStr) { + if (!isHexColorString(hexColorStr) ) { + throw new Error(`hexColorStr: '${hexColorStr}' is invalid.`); + } +} +export function getEuclideanDistance(arr1, arr2) { + if (arr1.length !== arr2.length) { + throw new Error('Both arrays must have the same length'); + } + let sum = 0; + for (let i = 0; i < arr1.length; i++) { + sum += Math.pow(arr1[i] - arr2[i], 2); + } + return Math.sqrt(sum); +} + export const isString = (value) => (typeof value === 'string' || value instanceof String); export const isNumber = (value) => typeof value === 'number' && !isNaN(value); export const validateKey = (obj, key) => { if (!(key in obj)) throw new Error(`Key '${key}' not found in object`); }; @@ -18,7 +41,10 @@ export const toFixedPoint = (value, precision) => +value.toFixed(precision); export const linearInterp = (x, x1, y1, x2, y2) => y1 + ((x - x1) / (x2 - x1)) * (y2 - y1); export const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; export const zeroPad = (num, places) => num.toString().padStart(places, "0"); +// given RGB array [R, G, B] return HSV array [ h, s, v] export const get_HSV_from_RGB = ([ R, G, B ]) => { + const RGB = [R,G,B]; + validateRGB(RGB); const min = Math.min(R, G, B); const max = Math.max(R, G, B); const delta = max - min; @@ -26,14 +52,76 @@ export const get_HSV_from_RGB = ([ R, G, B ]) => { let h = max === min ? 0 : (max === R ? (G - B) / delta + (G < B ? 6 : 0) : max === G ? (B - R) / delta + 2 : (R - G) / delta + 4) * 60; if (isNaN(h)) h = 0; - return [ h, s, max ]; + const v = max; + const HSV = [ h, s, v ].map(Math.round); + validateHSV(HSV); + return HSV; }; + +// given HSV array [h,s,v] return RGB array [r,g,b] export const get_RGB_from_HSV = ([ h, s, v ]) => { + const HSV = [h,s,v]; + validateHSV(HSV); const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0); - return [ f(5), f(3), f(1) ].map(Math.round); + const RGB = [ f(5), f(3), f(1) ].map(Math.round); + validateRGB(RGB); + return RGB; }; -// returns a 3-element array of integers or null +function test_HSV_RGB_functions() { + function test_get_HSV_from_RGB() { + const RGBIn = [64, 128, 255]; + const HSV = get_HSV_from_RGB([RGBIn[0],RGBIn[1],RGBIn[2]]); + const RGBOut = get_RGB_from_HSV([HSV[0],HSV[1],HSV[2]]); + console.assert( getEuclideanDistance(RGBOut, RGBIn) < EPSILON); + } + function test_get_RGB_from_HSV() { + const HSVIn = [180, 0, 1]; // H in [0..360], S in [0..1], V in [0..1] + const RGB = get_RGB_from_HSV([HSVIn[0],HSVIn[1],HSVIn[2]]); + const HSVOut = get_HSV_from_RGB([RGB[0],RGB[1],RGB[2]]); + console.assert( getEuclideanDistance(HSVOut, HSVIn) < EPSILON); + } + test_get_HSV_from_RGB(); + test_get_RGB_from_HSV(); +} + +export function isHSV(HSV) { + if( !Array.isArray(HSV) || HSV.length != 3 ) { + return false; + } else if ( HSV[0] < 0.0 || HSV[0] > 360.0 ) { + return false; + } else if ( HSV[1] < 0.0 || HSV[1] > 1.0 ) { + return false; + } else if ( HSV[2] < 0.0 || HSV[2] > 1.0 ) { + return false; + } + return true; +} + +export function validateHSV(HSV) { + if ( !isHSV(HSV) ) { + throw new Error(`HSV:[${HSV}] is invalid`); + } +} + +export function isRGB(RGB) { + if( !Array.isArray(RGB) || RGB.length != 3 ) { + return false; + } else if ( RGB[0] < 0 || RGB[0] > 255 ) { + return false; + } else if ( RGB[1] < 0 || RGB[1] > 255 ) { + return false; + } else if ( RGB[2] < 0 || RGB[2] > 255 ) { + return false; + } + return true; +} + +export function validateRGB(RGB) { + if ( !isRGB(RGB) ) { + throw new Error(`RGB:[${RGB}] is invalid`); + } +} export function get_RGB_from_RgbStr(rgbStr) { if ( isString(rgbStr) ) { rgbStr = rgbStr.replaceAll(" ",""); @@ -44,52 +132,98 @@ export function get_RGB_from_RgbStr(rgbStr) { const R = parseInt(rStr, 10); const G = parseInt(gStr, 10); const B = parseInt(bStr, 10); - return [ R, G, B ]; + const RGB = [ R, G, B ]; + if( isRGB(RGB) ) + return RGB; } } return null; } - -export function get_ColorStr_from_RGB(RGB) { - validateIntArrayLength(RGB,3); - return `color(${RGB[0]}, ${RGB[1]}, ${RGB[2]})`; -} - -export function get_rgbStr_from_RGB(RGB) { - validateIntArrayLength(RGB,3); +export function get_RgbStr_from_RGB(RGB) { return `rgb(${RGB[0]}, ${RGB[1]}, ${RGB[2]})`; } +export function test_RGB_RgbStr_functions() { + function test_get_RGB_from_RgbStr() { + const rgbStrIn = 'rgb(255, 64, 127)'; + const RGB = get_RGB_from_RgbStr(rgbStrIn); + const rgbStrOut = get_RgbStr_from_RGB(RGB); + console.assert(rgbStrIn === rgbStrOut); + } + function test_get_RgbStr_from_RGB() { + const rgbIn = [255, 0, 0]; + const rgbStr = get_RgbStr_from_RGB(rgbIn); + const rgbOut = get_RGB_from_RgbStr(rgbStr); + console.assert(arraysAreEqual(rgbOut, rgbIn)); + } + test_get_RGB_from_RgbStr(); + test_get_RgbStr_from_RGB(); +} -// returns a 3-element array of integers or null export function get_RGB_from_ColorStr(colorStr) { - if ( isString(colorStr) ) { - if (colorStr.startsWith("#")) { - return get_RGB_from_Hex(colorStr); - } - else if (colorStr.startsWith('rgb')) { - return get_RGB_from_RgbStr(colorStr); + if ( isString(colorStr) && colorStr.length > 6) { + colorStr = colorStr.replaceAll(" ",""); + const regex = /color\((\d+),(\d+),(\d+)\)/; + const matches = colorStr.match(regex); + var RGB = []; + if (matches) { + const [ , rStr, gStr, bStr ] = matches; + const R = parseInt(rStr, 10); + const G = parseInt(gStr, 10); + const B = parseInt(bStr, 10); + RGB = [ R, G, B ]; } - else if (colorStr.startsWith('color')) { - let hex = get_Hex_from_ColorStr(colorStr); + return RGB; + } + return null; +} + +export function get_ColorStr_from_RGB(RGB) { + validateRGB(RGB); + return `color(${RGB[0]}, ${RGB[1]}, ${RGB[2]})`; +} +// returns a 3-element array of integers or null +export function get_RGB_from_AnyStr(anyStr) { + if ( isString(anyStr) ) { + let hex = css_colors.get_HEX_from_CssColor(anyStr); + if ( isHexColorString(hex) ) { return get_RGB_from_Hex(hex); + } else if ( isHexColorString(anyStr) ) { + return get_RGB_from_Hex(anyStr); + } else if ( anyStr.startsWith('rgb') ) { + return get_RGB_from_RgbStr(anyStr); + } else if ( anyStr.startsWith('color') ) { + return get_RGB_from_ColorStr(anyStr); + } else { + console.trace(`anyStr:[${anyStr}] unable to find matching RGB converter`); + return null; } } + console.trace(`anyStr:[${anyStr}] is undefined, null, or blank`); return null; } +function test_RGB_ColorStr_functions() { + function test_get_ColorStr_from_RGB() { + const RGBin = [127, 64, 255]; + const ColorStr = get_ColorStr_from_RGB(RGBin); + const RGBout = get_RGB_from_ColorStr(ColorStr); + console.assert( arraysAreEqual(RGBout, RGBin) ); + } + function test_get_RGB_from_ColorStr() { + const ColorStrIn = "color(127, 64, 255)"; + const RGB = get_RGB_from_ColorStr(ColorStrIn); + const ColorStrOut = get_ColorStr_from_RGB(RGB); + console.assert( ColorStrOut == ColorStrIn ); + } + test_get_ColorStr_from_RGB(); + test_get_RGB_from_ColorStr(); +} + export function get_Hex_from_ColorStr(colorStr) { - var RGB = get_RGB_from_ColorStr(colorStr); + var RGB = get_RGB_from_AnyStr(colorStr); return get_Hex_from_RGB(RGB); } -export function isHexColorString(hexColorStr) { // enforces uppercase hex string only - return isString(hexColorStr) && /^#[0-9A-F]{6}$/.test(hexColorStr); -} -export function validateHexColorString(hexColorStr) { - if (!isHexColorString(hexColorStr) ) { - throw new Error(`hexColorStr: '${hexColorStr}' is invalid.`); - } -} export function normalizeHexColorString(hexColorStr) { // Create a dummy element to leverage the browser's color parsing var dummy = document.createElement("div"); @@ -216,8 +350,11 @@ export function validateIsPlainObject(obj) { throw new Error(`Error: argument is not a plain object, it is a(n) ${typeof obj} with value ${obj}`); } } +export function isElement(obj) { + return (obj instanceof HTMLElement); +} export function validateIsElement(obj) { - if (!(obj instanceof HTMLElement)) { + if (!isElement(obj)) { throw new Error(`Argument is not an HTML element. but it is a(n) ${typeof obj} with value ${obj}`); } } @@ -256,6 +393,11 @@ export function getStyleProps(element) { return styleProps; } +export function getStylePropsString(styleProps) { + validateIsStyleProps(styleProps); + return JSON.stringify(styleProps,null,2); +} + // z-index and background-color are styleProps export function applyStyleProps(element, styleProps) { validateIsStyleProps(styleProps); @@ -278,44 +420,55 @@ export function validateIsStylePropsArray(obj) { validateIsStyleProps(element); }); } +export function isDivElement(obj) { + return (obj instanceof HTMLElement) && (obj.tagName == 'DIV'); +} export function validateIsDivElement(obj) { - if (!(obj instanceof HTMLElement) || obj.tagName !== 'DIV') { - throw new Error(`Argument is not an HTML div element. bit is a(n) ${typeof obj} with value ${obj}`); + if (!isDivElement(obj)) { + throw new Error(`Argument is not an HTML DIV element. bit is a(n) ${typeof obj} with value ${obj}`); } } +export function isLineItemElement(obj) { + return (obj instanceof HTMLElement) && (obj.tagName == 'LI') +} export function validateIsLineItemElement(obj) { - if (!(obj instanceof HTMLElement) || obj.tagName !== 'LI') { - throw new Error(`Argument is not an HTML li element, but is a(n) ${typeof obj} with value ${obj}`); + if (!isLineItemElement(obj)){ + throw new Error(`Argument is not an HTML LI element, but is a(n) ${typeof obj} with value ${obj}`); } } +export function isCardDiv(obj) { + return isDivElement(obj) && obj.classList.contains('card-div'); +} + export function validateIsCardDiv(obj) { - validateIsDivElement(obj); - if (!obj.classList.contains('card-div')) { + if (!isCardDiv(obj)) { throw new Error(`Argument does not have "card-div" class but does have ${obj.classList}.`); } } +export function isBizcardDiv(obj) { + return isDivElement(obj) && obj.classList.contains('bizcard-div') +} export function validateIsBizcardDiv(obj) { - validateIsDivElement(obj); - if (!obj.classList.contains('bizcard-div')) { + if (!isBizcardDiv(obj)) { throw new Error(`Argument does not have "bizcard-div" class but does have ${obj.classList}.`); } } +export function isCardDivOrBizcardDiv(obj) { + return isCardDiv(obj) || isBizcardDiv(obj); +} export function validateIsCardDivOrBizcardDiv(obj) { - validateIsDivElement(obj); - if (!obj.classList.contains('card-div') && !obj.classList.contains('bizcard-div')) { + if (!isCardDivOrBizcardDiv(obj)) { throw new Error(`Argument does not have "card-div" or "bizcard-div" class but does have ${obj.classList}.`); } } +export function isCardDivLineItem(obj) { + return isLineItemElement(obj) && obj.classList.contains('card-div-line-item'); +} export function validateIsCardDivLineItem(obj) { - validateIsLineItemElement(obj); - if (!obj.classList.contains('card-div-line-item')) { + if (!isCardDivLineItem(obj)) { throw new Error(`Argument does not have "card-div-line-item" class but does have ${obj.classList}.`); } } -export function getStylePropsString(styleProps) { - validateIsStyleProps(styleProps); - return JSON.stringify(styleProps,null,2); -} // -------------------------------------- // Javascript hacks @@ -395,24 +548,27 @@ export function formatNumber(num, format) { } export function ensureHexColorStringAttribute(obj, attr) { - let color = obj.getAttribute(attr); - if( typeof color === 'undefined' || color === null || color === "") { - throw new Error(`Attribute ${attr} must be defined.`); - } - var hex = null; - if ( isHexColorString(color) ) { - hex = color; - } else if ( isNumericArray(color) && color.length === 3 ) { - hex = get_Hex_from_RGB(color); - } else if ( color.startWith('color') ) { - hex = get_Hex_from_ColorStr(color); - } - if (hex !== null) { - obj.setAttribute(attr, hex); - } else { - throw new Error(`Attribute ${attr} is not a valid hex color string.`); + let val = null; + let hex = null; + if ( isElement(obj) ) { + if( isString(attr) ) { + val = obj.getAttribute(attr); + if( isString(val) ) { + if ( isHexColorString(val) ) { + return; + } + var RGB = get_RGB_from_AnyStr(val); + if ( isRGB(RGB) ) { + hex = get_Hex_from_RGB(RGB); + if ( isHexColorString(hex) && hex != val) { + obj.setAttribute(attr, hex); + return; + } + } + } + } } - validateHexColorString(obj.getAttribute(attr)); + throw new Error(`obj:[${obj}] attr:[${attr}] val:[${val}] hex:[${hex}] is not a valid hexColorString.`); } export function ensureHexColorStringStyle(obj, styleName) { @@ -435,4 +591,36 @@ export function ensureHexColorStringStyle(obj, styleName) { } validateHexColorString(obj.style['styleName']); -} \ No newline at end of file +} + +export function getObjectAsString(obj) { + let str = ""; + for (let key in obj) { + let comma = (str === "") ? "" : ", "; + str += `${comma}${key}:${obj[key]}`; + } + return str; +} + +export function getAttributesAsObject(element) { + let attributes = {}; + for (let attribute of element.attributes) { + attributes[attribute.name] = attribute.value; + } + return attributes; +} +export function getAttributesAsString(element) { + let attributes = getAttributesAsObject(element); + return getObjectAsString(attributes); +} + +export function getDatasetAsString(element) { + let dataset = element.dataset; + return getObjectAsString(dataset); +} + +export function testColorFunctions() { + test_RGB_RgbStr_functions(); + test_RGB_ColorStr_functions(); +} + diff --git a/scratch.html b/scratch.html index 38d32fd..e9a620b 100644 --- a/scratch.html +++ b/scratch.html @@ -1 +1,22 @@ -mindset \ No newline at end of file + + Cigna Group +
+ + +
+ +As a senior data engineer in the data cyber security team of the Cigna Group
created a [REST API] using [Postman](https://www.postman.com/), [bash], [Linux], +and [OpenAPI](https://openapi-generator.tech/) for pulling credentials from the [CyberArk identity security +platform](https://www.cyberark.com/) using [mutual TLS SSL +authentication](https://docs.solace.com/Security/Two-Way-SSL-Authentication.htm) with [Amazon API +Gateway](https://docs.aws.amazon.com/apigateway/). \ No newline at end of file diff --git a/static_content/icons/icons8-image-16-black.png b/static_content/icons/icons8-img-16-black.png similarity index 100% rename from static_content/icons/icons8-image-16-black.png rename to static_content/icons/icons8-img-16-black.png diff --git a/static_content/icons/icons8-image-16-white.png b/static_content/icons/icons8-img-16-white.png similarity index 100% rename from static_content/icons/icons8-image-16-white.png rename to static_content/icons/icons8-img-16-white.png diff --git a/static_content/icons/icons8-geography-16-black.ico b/static_content/icons/icons8-url-16-black.ico similarity index 100% rename from static_content/icons/icons8-geography-16-black.ico rename to static_content/icons/icons8-url-16-black.ico diff --git a/static_content/icons/icons8-geography-16-black.png b/static_content/icons/icons8-url-16-black.png similarity index 100% rename from static_content/icons/icons8-geography-16-black.png rename to static_content/icons/icons8-url-16-black.png diff --git a/static_content/icons/icons8-geography-16-white.ico b/static_content/icons/icons8-url-16-white.ico similarity index 100% rename from static_content/icons/icons8-geography-16-white.ico rename to static_content/icons/icons8-url-16-white.ico diff --git a/static_content/icons/icons8-geography-16-white.png b/static_content/icons/icons8-url-16-white.png similarity index 100% rename from static_content/icons/icons8-geography-16-white.png rename to static_content/icons/icons8-url-16-white.png diff --git a/static_content/jobs/convert-jobs-xslx-to-mjs.sh b/static_content/jobs/convert-jobs-xslx-to-mjs.sh index bf02a1c..253031a 100755 --- a/static_content/jobs/convert-jobs-xslx-to-mjs.sh +++ b/static_content/jobs/convert-jobs-xslx-to-mjs.sh @@ -42,6 +42,6 @@ cat jobs.json >> jobs.mjs truncate -s -1 jobs.mjs echo ";" >> jobs.mjs type deactivate &>/dev/null && deactivate -rm -f jobs.csv jobs.json +# rm -f jobs.csv jobs.json rm -rf venv echo "done" \ No newline at end of file diff --git a/static_content/jobs/csv2json.py b/static_content/jobs/csv2json.py index e256a02..2f88f2d 100644 --- a/static_content/jobs/csv2json.py +++ b/static_content/jobs/csv2json.py @@ -7,7 +7,7 @@ csv.field_size_limit(sys.maxsize) replacements = { - "CURRENT_DATE": f"{datetime.now():%Y-%m}" + "CURRENT_DATE": f"{datetime.now():%Y-%m-%d}" } in_str = sys.stdin.read() reader_list = csv.DictReader(io.StringIO(in_str)) diff --git a/static_content/jobs/jobs.csv b/static_content/jobs/jobs.csv new file mode 100644 index 0000000..a4079f5 --- /dev/null +++ b/static_content/jobs/jobs.csv @@ -0,0 +1,89 @@ +role,employer,start,end,z-index,css name,css RGB,css color,text color,Description +Senior Data Engineer ,The Cigna Group,2023-05-01,CURRENT_DATE,3,darkcyan,#006688,,#FFFFFF,"• As a senior data engineer in the data cyber security team of the [Cigna Group](https://www.thecignagroup.com/) created a [REST API](url) using [Postman](https://www.postman.com/), [bash], [Linux], and [OpenAPI](https://openapi-generator.tech/) for pulling credentials from the [CyberArk identity security platform](https://www.cyberark.com/) using [mutual TLS SSL authentication](https://docs.solace.com/Security/Two-Way-SSL-Authentication.htm) with [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/). +• Migrated a suite of legacy data pipeline [Python] elements running on the [Unity IoC platform](http://unitycontainer.org/articles/introduction.html) to pull credentials from the CyberArk service at runtime rather than using [Fernet](https://cryptography.io/en/latest/fernet/) encrypted local files. +• Upgraded [GitHub] apps to use [Jenkins](https://docs.aws.amazon.com/apigateway/) CI/CD pipeline for build, applying sofware and cyber-secutity code checks, and on-prem server installation." +Senior Data Engineer ,Warner Brothers Interactive Entertainment,2022-09-01,2023-05-01,2,blue,#0000ff,,#FFFFFF,"• As a senior data engineer in the analytics team of [Warner Brothers Interactive Entertainment](https://warnerbrosgames.com/) Division, I implemented high-volume pipeline integrations shuffling game telemetry and [user PII data] between WB-distributed consumer games and [marketing service platforms] via [Segment customer data platform](https://segment.com/customer-data-platform/) using [Kafka](https://aws.amazon.com/msk/), [Amazon Redshift](https://aws.amazon.com/redshift/), and [Apache Airflow](https://airflow.apache.org). +• Employed [Python], [GitHub], [bash], [Linux], [Amazon Glue](https://aws.amazon.com/glue/) and [Apache Airflow](https://airflow.apache.org/) for external 3rd-party integrations and internal dev-ops integrations with [Jenkins], [DataDog](https://www.datadoghq.com/), and [ZenDesk](https://zendesk.com) +• Integrated with [Google BigQuery data warehouse](https://cloud.google.com/bigquery using [Apache Airflow](https://aws.amazon.com/managed-workflows-for-apache-airflow/), [Amazon S3], and [Amazon Redshift](https://aws.amazon.com/redshift/)." +Senior Data Engineer ,Angel Studios ,2021-11-01,2022-09-01,1,mediumblue,#4400cd,,#FFFFFF,"• As a senior data engineer for [Angel Studios](https://www.angel.com/home), a streaming media service that offers family-friendly entertainment that amplifies light, with titles including The Chosen, Dry Bar Comedy, and Tuttle Twins. +• Used [Python], [GitHub], [Pandas], [Numpy], [Keras], [bash], [Linux], and [Jupyter](https://jupyter.org/) to build and tune hyperparameters of a [convolutional neural network](https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53) with [supervised learning] on [Amazon Sagemaker](https://aws.amazon.com/pm/sagemaker/) to classify movie frames from episodic programs stored in [Amazon S3](https://aws.amazon.com/s3/storage-classes). +• Built web client apps using [Python] with [Postman](https://www.postman.com/) that made [REST API] requests to pull monthly usage data from various web marketing partners like [FaceBook Marketing](https://www.quora.com/What-is-Facebook-Marketing-1), [Google Play](https://play.google/howplayworks/) , and [Vimeo](https://vimeo.com/). +• Worked with [Segment customer data platform](https://segment.com/customer-data-platform/), [Excel], and [Tableau] to create scheduled reports for the company's sales and finance teams." +Senior Data Engineer ,Greenseed Tech,2020-11-01,2021-11-01,2,blueviolet,#8a2be2,,#FFFFFF,"• As a senior software engineer for Greenseed Tech, an internet company that provides daily lead reports for independent real-estage agents world-wide, I [containerized] legacy web applications using [bash], [Linux], [GitHub], [Docker](https://www.docker.com/) and [Amazon Secrets Manager](https://aws.amazon.com/secrets-manager/). +• Updated legacy web apps using [bash], [Linux], [HTML], [CSS], [JavaScript], [NGINX], and [OpenSSL]. +• Documented existing data architecture as [ERDs](https://www.lucidchart.com/pages/er-diagrams) using [DBeaver Enterprise](https://dbeaver.com/dbeaver-enterprise/). " +Senior Full-Stack Developer ,NuSkin,2019-11-01,2020-11-01,1,purple,#800080,,#FFFFFF,"• As a senior full stack developer for [NuSkin](https://www.nuskin.com/us/en/, an international company known for its excellent skin and beauty products I created new [Vue.js](https://vuejs.org/), [Nuxt](https://nuxt.com/), and [Vuetify](https://vuetifyjs.com/en/) components using [bash], [Linux], [GitHub], [NodeJS], [HTML] and [CSS]. +• Internationalized content using [Adobe Experience Cloud](https://business.adobe.com/)." +Senior Data Engineer ,SeniorLink,2017-03-01,2019-11-01,2,maroon,#800000,,#FFFFFF,"• As a senior data engineer for SeniorLink's [Vela project]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Vela-150x126.png} a homeservices support platform, helped create [ETL](https://aws.amazon.com/what-is/etl/) processes using [Amazon Kinesis](https://aws.amazon.com/pm/kinesis/), [Python], [PySpark](https://spark.apache.org/), and [Amazon Data Pipeline](https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/what-is-datapipeline.html) to load structured event data from [PostgreSQL] databases into [Amazon Redshift](https://aws.amazon.com/pm/redshift/). +• Saved data to [Amazon S3] using [Amazon Kinesis] and triggered [Amazon Lambda](https://docs.aws.amazon.com/lambda/) jobs to aggregate steaming event data into [schema-on-read] file formats, [Apache Avro](https://avro.apache.org/) and [Apache Parquet](https://parquet.apache.org/). +• Steered efforts in creating a [Data Lake](https://aws.amazon.com/big-data/datalakes-and-analytics/datalakes/) using [PostgreSQL] and [FlyWay](https://flywaydb.org/) with [Python] and [PySpark](https://spark.apache.org/docs/latest/api/python/index.html) pre-processing on [EC2 instances] using shared [Amazon EFS](https://zesty.co/blog/ebs-vs-efs-which-is-right) for staged storage. +• Used streaming event messages queued in [RabbitMQ](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/working-with-rabbitmq.html) and [Amazon Kinesis] to build [type-2 slowly changing dimensions] and accumulative facts tables. +• Designed and implemented a custom [star-schema warehouse](https://www.databricks.com/glossary/star-schema) and [ETL] processes to [de-normalize](https://en.wikipedia.org/wiki/Denormalization) and load data into [Amazon Redshift](https://aws.amazon.com/redshift/) data warehouse for BI reporting using [Tableau](https://www.tableau.com/). +• [Test-driven development](https://www.pluralsight.com/blog/software-development/tdd-vs-bdd) using [bash], [Linux], [Python], [PyCharm], [PyTest], [Unit-test], [GitHub], [Jira], and [Jenkins](https://www.jenkins.io/)." +Senior Back-End Engineer ,BigR.io,2016-12-01,2017-03-01,1,crimson,#dc143c,,#FFFFFF,"• As a senior software engineer at [BigR.io]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Bigr.io_-150x106.png} I used [Amazon microservices] for custom voice-based [natural language processing] applications. +• Used [Apache ActiveMQ](https://activemq.apache.org/), [Swagger](https://swagger.io/), [JSON], [Jackson](url), [AOP](https://www.baeldung.com/spring-aop), [Eclipse], [Maven], [GitHub], [Jira], and [Jenkins]. +• [Java], [J2EE], [Servlets], [Spring], [SpringBoot], [JAX-RS], [bash], [Linux], [JUnit], [JMeter], and [JProfile]" +Technical Lead / Co-Founder ,ClipFile LLC,2011-02-01,2016-12-01,2,orangered,#ff4500,,#000000,"• Co-founded [ClipFile]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/clipfile-infrastructure-150x150.png}, a company that envisioned building a web destination where users could easily record and share their favorite pieces of content like facts, authored stories, quotes, articles, chapters, or personal thoughts, as a way of concretely defining their personal [mindset]{https://sourcesofinsight.com/wp-content/uploads/2014/04/Mindset-768x505.jpg}(https://sourcesofinsight.com/what-is-mindset/). +• Implemented [fuzzy matching](https://nanonets.com/blog/fuzzy-matching-fuzzy-logic/), [word clustering](https://www.ilc.cnr.it/EAGLES96/rep2/node37.html#:~:text=Word%20clustering%20is%20a%20technique,to%20information%20retrieval%20and%20filtering.), [semantic similarity scores](https://towardsdatascience.com/semantic-similarity-using-transformers-8f3cb5bf66d6), and [collaborative filtering](https://www.hindawi.com/journals/aai/2009/421425/) to help users find content that matched or differed from thieir own mindset. +• Launched a novel [SaaS] using [Amazon Web Services] that let individuals and content creators search and share mindsets. +• Conceptualized patented technology by designing and implementing a fuil-stack consumer-facing content management system that supported tuned matching among selected attributes. +• [Java], [J2EE], [JSP], [Servlets], [Spring], [Amazon services], [JavaScript], [JQuery], [HTML], [CSS], [JUnit], [JMeter], [JProfile]. +• Utilized [REST API], [Swagger], [Apache Shiro](https://shiro.apache.org/), [Eclipse IDE](https://www.eclipse.org/home/whatis/), [Apache Maven](https://maven.apache.org/what-is-maven.html), [Apache Ant](https://ant.apache.org/), [GitHub], [Hibernate], [Amazon SimpleDB](https://aws.amazon.com/simpledb/), [CentOS Linux](https://www.centos.org/), [Apache Tomcat](https://tomcat.apache.org/), [bash], [Linux], [Jetty](https://projects.eclipse.org/projects/rt.jetty), and [Spring MVC](https://docs.spring.io/spring-framework/reference/web/webmvc.html). +• Served as co-founder and co-authored [four patents](https://www.freepatentsonline.com/y2013/0325870.html)." +Lead Solutions Architect / Co-Founder ,Sierra Vista Group LLC,2002-11-01,2011-02-01,1,orange,#ffa500,,#000000,"• Co-founded a finance and technology boutique called [Sierra Vista Group](https://6sense.com/company/sierra-vista-group-llc/5ba8a5247c8666394376fc4f) that delivered support in planning and proposing effective IT strategies for key clients in several industries. +• Performed various services, including system and architecture assessment and solutions design, to ensure the smooth running of technical projects. +• Managed project schedules and technical specifications to match business requirements within contractual budget constraints. +• Identified opportunities for potential clients requiring expertise in product development, software engineering, and data modeling. Negotiated and communicated with c-level client management regarding project milestone agreements. +• Increased ROI for each client’s project by hiring and managing contractors to deliver custom software solutions. +• Delivered high-level leadership and guidance to a team of software engineering consultants for several projects to accelerate operational excellence." +Technical Lead / Co-Founder ,HomePorfolio LLC ,1998-02-01,2002-11-01,1,teal,#008080,,#FFFFFF,"• As co-founder and CTO, designed and led the development of a public website used by discerning home designers and builders called [HomePortfolio.com](https://homeportfolio.com/). +• Hired a staff of 10 software and databases developers. +• Worked with data acquisition team to scan and tag over 700,000 premium home design products from over 2,000 manufactures and vendors. +• Designed datamodel and data entry tools for category-specific product attribution. +• Helped extended the business model to provide online product selection tools for participating vendors and manufacturers. +• Instrumental in raising over $70M in venture capital. +• Used [Oracle], [ATG Dyanamo]( https://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGPersBusinessGuide/html/s0102dynamoapplicationframework01.html), [Java], [Akamai]{https://www.hiclipart.com/free-transparent-background-png-clipart-zkmsn}(https://www.akamai.com/), [WebTrends](https://www.webtrends.com/), [FileMakerPro], [ImageMagik](https://imagemagick.org/index.php), [bash], [Linux], [HTML], [JavaScript], [CSS], and [Omnigraffle](https://www.omnigroup.com/omnigraffle) for data modeling and workflow designs." +Lead Software Developer ,BuildingBlocks LLC ,1996-06-01,1998-02-01,1,darkcyan,#008b8b,,#FFFFFF,"• As lead software developer, built a CD-ROM-based home design application for selecting premium home design products for previewing in the context of images of any household rooms. +• Built the prototype using Adobe Photoshop and [Macromedia Director](https://macromedia.fandom.com/wiki/Macromedia_Director). +• Built the actual application using using [bash], [Linux], [Java] and [Marimba Bongo](https://www.thriftbooks.com/w/official-marimba-guide-to-bongo_danny-goodman/2574616/#edition=58026223&idiq=42367912) widget layout tool. +• Updates for the self-updating application were delivered over the internet using [Marimba Castanet](https://www.infoworld.com/article/2076707/marimba-launches-new-castanet-with-a-less-java-centric-focus.html) push-technology." +Ph.D. Media Arts & Science,MIT Media Lab,1990-09-01,1997-04-01,2,blue,#0000ff,,#FFFFFF,"• Doctor of Philosopy degree, [Massachusetts Institute of Technology]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/MIT-logo.png}, Cambridge, Massachusettes +• Media Laboratory, Media Arts and Sciences +• Took courses in machine vision, signals and systems, digital signal processing, and stochastics. +• Helped build the operating system for the [Cheops multi-processor system](http://alumni.media.mit.edu/~wad/cheops_CSVT/cheops.html) used for digital video research and for holographic video +• [“Vision-assisted modeling for model-based video representations”](https://dspace.mit.edu/handle/1721.1/29123), (Ph.D. Dissertation) MIT, Program in Media Arts & Sciences, 1997 +• [“Semiautomatic 3-D Model Extraction from Uncalibrated 2-D Camera Views.”](https://www.media.mit.edu/publications/semiautomatic-3-d-model-extraction-from-uncalibrated-2-d-camera-views-2/) S. Becker & V. M. Bove, Jr., Proc. SPIE Image Synthesis, 2410, 1995, pp. 447-461. +• “Semiautomatic Scene Modeling From 2-D Views with Partially Known Structure.” Shawn Becker, MIT Media Lab Reports, 1995 +• “Semiautomatic Camera Lens Calibration from Partially Known Structure”, Shawn Becker, MIT Media Lab Reports, 1994 +• [“Formulating a scene probability equation to differentiate the effects of shape & albedo on image brightness.”](https://www.researchgate.net/publication/2668457_Formulating_a_Scene_Probability_Equation_to_Differentiate_the_Effects_of_Shape_and_Albedo_on_Image_Brightness) Shawn Becker, MIT Media Lab Reports, 1994 +• “Computation of some projective-chirplet-transform & metaplectic-chirplet-transform subspaces, with applications in image processing.” Steve Mann & Shawn Becker, DSP World Symposium, Boston, Massachusetts, November 1992. +• [C programming language], [TclTk], [X11], [HTML], [JavaScript],[CSS],[XMotif], [bash], [Linux]" +MS Computer Science,BYU,1987-09-01,1990-09-01,2,mediumblue,#0000cd,,#FFFFFF,"• Masters of Science degree, [Brigham Young University]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-entrance-150x150.jpg}, Provo, Utah +Took all courses required for both bachelors and masters degrees in Computer Science +• Thesis project [“Interactive Measurement of Three-Dimensional Objects Using a Depth Buffer & Linear Probe.”](https://dl.acm.org/doi/pdf/10.1145/108360.108446) CS MS Thesis, Shawn Becker, William A. Barrett & Dan R. Olsen, ACM Transactions on Graphics, Vol. 10, No. 2, April 1991 +• Top Research Presentation – New Tech Research Conference - Brigham Young University – Provo, UT – March 1990 +• [“Fast Automated Object Detection Using Signature Parsing.”](https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1192/1/Fast-Automated-Object-Detection-Using-Signature-Parsing/10.1117/12.969720.short) Tim Heaton; Shawn Becker; Kelley Anderson; William Barrett: Proceedings Volume 1192, Intelligent Robots & Computer Vision VIII: Algorithms & Techniques; (1990) https://doi.org/10.1117/12.969720 +• [“Probabilistic Segmentation of Myocardial Tissue by Deterministic Relaxation.”](https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1737&context=facpub) Jerome A. Broekhuijsen, Shawn C. Becker, & William A. Barrett: IEEE Proceedings of Computers in Cardiology, pp. 99-12, Jerusalem, September 1989. +• [“Interactive Measurement of three-Dimensional Cardiac Morphology.”]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-MS-CS-Skull-Cross-Section-1.jpeg}(https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1736&context=facpub) Shawn C Becker, William A Barrett, October 1989, DOI: 10.1109/CIC.1989.130586, Conference: Computers in Cardiology. +• [C programming language], [bash], [Linux], [XMotif], and [X11]." +Full Stack Developer,Cimmetrix LLC,1988-06-01,1989-09-01,3,blueviolet,#8a2be2,,#FFFFFF,"• Front-end software developer of a reverse kinametics path planning system for multi-axis industrial robots for [Cimmetrix]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Cimetrix-PDF-combined-logo-150x100.png}. +• Technologies used include [bash], [Linux], [C programming language], [bash](https://en.wikipedia.org/wiki/Bourne_shell), [X11] , [Xt toolkit intrinsics](https://en.wikipedia.org/wiki/X_Toolkit_Intrinsics), [Silicon Graphics Irix](https://en.wikipedia.org/wiki/Silicon_Graphics), and [HP-UX](https://en.wikipedia.org/wiki/HP-UX)." +Project Manager / Technical Lead ,MSC ,2007-12-01,2010-08-01,2,yellow,#ffff00,,#000000,"• MSC, now called [OneCall](https://onecallcm.com/), is a leading workers compensation services company. +• As project manager and technical lead for this Sierra Vista Group project, I presented fixed schedule-fixed budget project proposals to C-level executives to add features to their legacy call center system used by 10 different healthcare divisions. +• Interviewed stakeholders to create functional requirements and technical spefications for each stage of development. +• Worked with development team to create work plan, assign tasks. +• Oversaw quality assurance and customer approval testing. +• Used the MS Office suite of business apps a well as MS Visio. " +Senior Architect ,Eleven LLC,2006-02-01,2007-12-01,2,lime,#00ff00,,#000000,"• [Eleven LLC](https://www.eleven.net/) built mobile apps used by beverage industry distributors to help manage placement of their products in the shelves and coolers in retail locations. The work done by the Sierra Vista Group was instrumental in their company being acquired by [Trimble Mobile Solutions](https://help.trimblegeospatial.com/TMM/Home.htm). +• As the architect and team lead, we used [Java], [bash], [GitHub], [Linix], and [JBoss](https://developers.redhat.com/products/eap/overview) message-oriented middleware platform, [Sybase Anywhere](https://texas.gs.shi.com/Product/30451452/Sybase-SQL-Anywhere-Advanced-Edition) for the client/server based database, and [Windows Mobile](https://en.wikipedia.org/wiki/Windows_Mobile_5.0) running on ruggedized mobile devices. " +Senior Architect,Intrusic LLC,2005-02-01,2006-02-01,2,limegreen,#32cd32,,#000000,"• [Intrusic LLC](https://www.crunchbase.com/organization/intrusic) built real-time network monitoring systems that identified external and internal network intrusion attempts +• As a Sierra Vista Group architech, I helped design and develop an approach for buffering live streaming network traffic for asynchronous package processing. +• Used [Debian Linux](https://www.debian.org/), [C programming language](https://www.cprogramming.com/books/ritchie.html), and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software)." +Project Manager / Technical Lead ,AMI Entertainment ,2004-02-01,2005-02-01,2,olivedrab,#6b8e23,,#000000,"• AMI (https://amientertainment.com/) was the internet-music distribution incarnation of Rowe International. +• As a Sierra Vista Group project manager and technical lead, I helped design and implement their system for making monthly ACH royalty payments to music copyright owners for mechanical and performance licensing rights. +• Used [FileMaker Pro](https://www.claris.com/filemaker/), [bash], [Linux], [HTML], [CSS], [JavaScript], [Java], and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software)." +Project Manager / Technical Lead ,Rowe International,2003-03-01,2004-02-01,2,forestgreen,#228b22,,#000000,"• [Rowe International](https://pitchbook.com/profiles/company/13178-08) was the leading manufacturer of music jukeboxes. +• Sierra Vista Group was consulted to assess their available technologies and create a plan to build their back-end systems to let them become a leading provider of internet-based music. +• As project manager and technical lead created the project plan and led the development of a full-stack web application used by jukebox owners and Rowe sales and marketing. +• Used [Java], [bash], [Linux], [HTML], [CSS], [JavaScript], [ObjectDesign](https://object.design/), [MySQL](https://www.mysql.com/), and [Adobe Photoshop](https://www.adobe.com/products/photoshop.html). +" diff --git a/static_content/jobs/jobs.json b/static_content/jobs/jobs.json new file mode 100644 index 0000000..98aebb9 --- /dev/null +++ b/static_content/jobs/jobs.json @@ -0,0 +1 @@ +[{"role": "Senior Data Engineer ", "employer": "The Cigna Group", "start": "2023-05-01", "end": "2024-01-01", "z-index": "3", "css name": "darkcyan", "css RGB": "#006688", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior data engineer in the data cyber security team of the [Cigna Group](https://www.thecignagroup.com/) created a [REST API](url) using [Postman](https://www.postman.com/), [bash], [Linux], and [OpenAPI](https://openapi-generator.tech/) for pulling credentials from the [CyberArk identity security platform](https://www.cyberark.com/) using [mutual TLS SSL authentication](https://docs.solace.com/Security/Two-Way-SSL-Authentication.htm) with [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/). \n\u2022 Migrated a suite of legacy data pipeline [Python] elements running on the [Unity IoC platform](http://unitycontainer.org/articles/introduction.html) to pull credentials from the CyberArk service at runtime rather than using [Fernet](https://cryptography.io/en/latest/fernet/) encrypted local files. \n\u2022 Upgraded [GitHub] apps to use [Jenkins](https://docs.aws.amazon.com/apigateway/) CI/CD pipeline for build, applying sofware and cyber-secutity code checks, and on-prem server installation."},{"role": "Senior Data Engineer ", "employer": "Warner Brothers Interactive Entertainment", "start": "2022-09-01", "end": "2023-05-01", "z-index": "2", "css name": "blue", "css RGB": "#0000ff", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior data engineer in the analytics team of [Warner Brothers Interactive Entertainment](https://warnerbrosgames.com/) Division, I implemented high-volume pipeline integrations shuffling game telemetry and [user PII data] between WB-distributed consumer games and [marketing service platforms] via [Segment customer data platform](https://segment.com/customer-data-platform/) using [Kafka](https://aws.amazon.com/msk/), [Amazon Redshift](https://aws.amazon.com/redshift/), and [Apache Airflow](https://airflow.apache.org). \n\u2022 Employed [Python], [GitHub], [bash], [Linux], [Amazon Glue](https://aws.amazon.com/glue/) and [Apache Airflow](https://airflow.apache.org/) for external 3rd-party integrations and internal dev-ops integrations with [Jenkins], [DataDog](https://www.datadoghq.com/), and [ZenDesk](https://zendesk.com) \n\u2022 Integrated with [Google BigQuery data warehouse](https://cloud.google.com/bigquery using [Apache Airflow](https://aws.amazon.com/managed-workflows-for-apache-airflow/), [Amazon S3], and [Amazon Redshift](https://aws.amazon.com/redshift/)."},{"role": "Senior Data Engineer ", "employer": "Angel Studios ", "start": "2021-11-01", "end": "2022-09-01", "z-index": "1", "css name": "mediumblue", "css RGB": "#4400cd", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior data engineer for [Angel Studios](https://www.angel.com/home), a streaming media service that offers family-friendly entertainment that amplifies light, with titles including The Chosen, Dry Bar Comedy, and Tuttle Twins.\n\u2022 Used [Python], [GitHub], [Pandas], [Numpy], [Keras], [bash], [Linux], and [Jupyter](https://jupyter.org/) to build and tune hyperparameters of a [convolutional neural network](https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53) with [supervised learning] on [Amazon Sagemaker](https://aws.amazon.com/pm/sagemaker/) to classify movie frames from episodic programs stored in [Amazon S3](https://aws.amazon.com/s3/storage-classes). \n\u2022 Built web client apps using [Python] with [Postman](https://www.postman.com/) that made [REST API] requests to pull monthly usage data from various web marketing partners like [FaceBook Marketing](https://www.quora.com/What-is-Facebook-Marketing-1), [Google Play](https://play.google/howplayworks/) , and [Vimeo](https://vimeo.com/). \n\u2022 Worked with [Segment customer data platform](https://segment.com/customer-data-platform/), [Excel], and [Tableau] to create scheduled reports for the company's sales and finance teams."},{"role": "Senior Data Engineer ", "employer": "Greenseed Tech", "start": "2020-11-01", "end": "2021-11-01", "z-index": "2", "css name": "blueviolet", "css RGB": "#8a2be2", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior software engineer for Greenseed Tech, an internet company that provides daily lead reports for independent real-estage agents world-wide, I [containerized] legacy web applications using [bash], [Linux], [GitHub], [Docker](https://www.docker.com/) and [Amazon Secrets Manager](https://aws.amazon.com/secrets-manager/). \n\u2022 Updated legacy web apps using [bash], [Linux], [HTML], [CSS], [JavaScript], [NGINX], and [OpenSSL].\n\u2022 Documented existing data architecture as [ERDs](https://www.lucidchart.com/pages/er-diagrams) using [DBeaver Enterprise](https://dbeaver.com/dbeaver-enterprise/). "},{"role": "Senior Full-Stack Developer ", "employer": "NuSkin", "start": "2019-11-01", "end": "2020-11-01", "z-index": "1", "css name": "purple", "css RGB": "#800080", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior full stack developer for [NuSkin](https://www.nuskin.com/us/en/, an international company known for its excellent skin and beauty products I created new [Vue.js](https://vuejs.org/), [Nuxt](https://nuxt.com/), and [Vuetify](https://vuetifyjs.com/en/) components using [bash], [Linux], [GitHub], [NodeJS], [HTML] and [CSS]. \n\u2022 Internationalized content using [Adobe Experience Cloud](https://business.adobe.com/)."},{"role": "Senior Data Engineer ", "employer": "SeniorLink", "start": "2017-03-01", "end": "2019-11-01", "z-index": "2", "css name": "maroon", "css RGB": "#800000", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior data engineer for SeniorLink's [Vela project]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Vela-150x126.png} a homeservices support platform, helped create [ETL](https://aws.amazon.com/what-is/etl/) processes using [Amazon Kinesis](https://aws.amazon.com/pm/kinesis/), [Python], [PySpark](https://spark.apache.org/), and [Amazon Data Pipeline](https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/what-is-datapipeline.html) to load structured event data from [PostgreSQL] databases into [Amazon Redshift](https://aws.amazon.com/pm/redshift/). \n\u2022 Saved data to [Amazon S3] using [Amazon Kinesis] and triggered [Amazon Lambda](https://docs.aws.amazon.com/lambda/) jobs to aggregate steaming event data into [schema-on-read] file formats, [Apache Avro](https://avro.apache.org/) and [Apache Parquet](https://parquet.apache.org/).\n\u2022 Steered efforts in creating a [Data Lake](https://aws.amazon.com/big-data/datalakes-and-analytics/datalakes/) using [PostgreSQL] and [FlyWay](https://flywaydb.org/) with [Python] and [PySpark](https://spark.apache.org/docs/latest/api/python/index.html) pre-processing on [EC2 instances] using shared [Amazon EFS](https://zesty.co/blog/ebs-vs-efs-which-is-right) for staged storage.\n\u2022 Used streaming event messages queued in [RabbitMQ](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/working-with-rabbitmq.html) and [Amazon Kinesis] to build [type-2 slowly changing dimensions] and accumulative facts tables. \n\u2022 Designed and implemented a custom [star-schema warehouse](https://www.databricks.com/glossary/star-schema) and [ETL] processes to [de-normalize](https://en.wikipedia.org/wiki/Denormalization) and load data into [Amazon Redshift](https://aws.amazon.com/redshift/) data warehouse for BI reporting using [Tableau](https://www.tableau.com/).\n\u2022 [Test-driven development](https://www.pluralsight.com/blog/software-development/tdd-vs-bdd) using [bash], [Linux], [Python], [PyCharm], [PyTest], [Unit-test], [GitHub], [Jira], and [Jenkins](https://www.jenkins.io/)."},{"role": "Senior Back-End Engineer ", "employer": "BigR.io", "start": "2016-12-01", "end": "2017-03-01", "z-index": "1", "css name": "crimson", "css RGB": "#dc143c", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior software engineer at [BigR.io]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Bigr.io_-150x106.png} I used [Amazon microservices] for custom voice-based [natural language processing] applications.\n\u2022 Used [Apache ActiveMQ](https://activemq.apache.org/), [Swagger](https://swagger.io/), [JSON], [Jackson](url), [AOP](https://www.baeldung.com/spring-aop), [Eclipse], [Maven], [GitHub], [Jira], and [Jenkins].\n\u2022 [Java], [J2EE], [Servlets], [Spring], [SpringBoot], [JAX-RS], [bash], [Linux], [JUnit], [JMeter], and [JProfile]"},{"role": "Technical Lead / Co-Founder ", "employer": "ClipFile LLC", "start": "2011-02-01", "end": "2016-12-01", "z-index": "2", "css name": "orangered", "css RGB": "#ff4500", "css color": "", "text color": "#000000", "Description": "\u2022 Co-founded [ClipFile]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/clipfile-infrastructure-150x150.png}, a company that envisioned building a web destination where users could easily record and share their favorite pieces of content like facts, authored stories, quotes, articles, chapters, or personal thoughts, as a way of concretely defining their personal [mindset]{https://sourcesofinsight.com/wp-content/uploads/2014/04/Mindset-768x505.jpg}(https://sourcesofinsight.com/what-is-mindset/).\n\u2022 Implemented [fuzzy matching](https://nanonets.com/blog/fuzzy-matching-fuzzy-logic/), [word clustering](https://www.ilc.cnr.it/EAGLES96/rep2/node37.html#:~:text=Word%20clustering%20is%20a%20technique,to%20information%20retrieval%20and%20filtering.), [semantic similarity scores](https://towardsdatascience.com/semantic-similarity-using-transformers-8f3cb5bf66d6), and [collaborative filtering](https://www.hindawi.com/journals/aai/2009/421425/) to help users find content that matched or differed from thieir own mindset.\n\u2022 Launched a novel [SaaS] using [Amazon Web Services] that let individuals and content creators search and share mindsets.\n\u2022 Conceptualized patented technology by designing and implementing a fuil-stack consumer-facing content management system that supported tuned matching among selected attributes.\n\u2022 [Java], [J2EE], [JSP], [Servlets], [Spring], [Amazon services], [JavaScript], [JQuery], [HTML], [CSS], [JUnit], [JMeter], [JProfile].\n\u2022 Utilized [REST API], [Swagger], [Apache Shiro](https://shiro.apache.org/), [Eclipse IDE](https://www.eclipse.org/home/whatis/), [Apache Maven](https://maven.apache.org/what-is-maven.html), [Apache Ant](https://ant.apache.org/), [GitHub], [Hibernate], [Amazon SimpleDB](https://aws.amazon.com/simpledb/), [CentOS Linux](https://www.centos.org/), [Apache Tomcat](https://tomcat.apache.org/), [bash], [Linux], [Jetty](https://projects.eclipse.org/projects/rt.jetty), and [Spring MVC](https://docs.spring.io/spring-framework/reference/web/webmvc.html).\n\u2022 Served as co-founder and co-authored [four patents](https://www.freepatentsonline.com/y2013/0325870.html)."},{"role": "Lead Solutions Architect / Co-Founder ", "employer": "Sierra Vista Group LLC", "start": "2002-11-01", "end": "2011-02-01", "z-index": "1", "css name": "orange", "css RGB": "#ffa500", "css color": "", "text color": "#000000", "Description": "\u2022 Co-founded a finance and technology boutique called [Sierra Vista Group](https://6sense.com/company/sierra-vista-group-llc/5ba8a5247c8666394376fc4f) that delivered support in planning and proposing effective IT strategies for key clients in several industries. \n\u2022 Performed various services, including system and architecture assessment and solutions design, to ensure the smooth running of technical projects.\n\u2022 Managed project schedules and technical specifications to match business requirements within contractual budget constraints. \n\u2022 Identified opportunities for potential clients requiring expertise in product development, software engineering, and data modeling. Negotiated and communicated with c-level client management regarding project milestone agreements.\n\u2022 Increased ROI for each client\u2019s project by hiring and managing contractors to deliver custom software solutions.\n\u2022 Delivered high-level leadership and guidance to a team of software engineering consultants for several projects to accelerate operational excellence."},{"role": "Technical Lead / Co-Founder ", "employer": "HomePorfolio LLC ", "start": "1998-02-01", "end": "2002-11-01", "z-index": "1", "css name": "teal", "css RGB": "#008080", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As co-founder and CTO, designed and led the development of a public website used by discerning home designers and builders called [HomePortfolio.com](https://homeportfolio.com/). \n\u2022 Hired a staff of 10 software and databases developers. \n\u2022 Worked with data acquisition team to scan and tag over 700,000 premium home design products from over 2,000 manufactures and vendors.\n\u2022 Designed datamodel and data entry tools for category-specific product attribution. \n\u2022 Helped extended the business model to provide online product selection tools for participating vendors and manufacturers.\n\u2022 Instrumental in raising over $70M in venture capital. \n\u2022 Used [Oracle], [ATG Dyanamo]( https://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGPersBusinessGuide/html/s0102dynamoapplicationframework01.html), [Java], [Akamai]{https://www.hiclipart.com/free-transparent-background-png-clipart-zkmsn}(https://www.akamai.com/), [WebTrends](https://www.webtrends.com/), [FileMakerPro], [ImageMagik](https://imagemagick.org/index.php), [bash], [Linux], [HTML], [JavaScript], [CSS], and [Omnigraffle](https://www.omnigroup.com/omnigraffle) for data modeling and workflow designs."},{"role": "Lead Software Developer ", "employer": "BuildingBlocks LLC ", "start": "1996-06-01", "end": "1998-02-01", "z-index": "1", "css name": "darkcyan", "css RGB": "#008b8b", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As lead software developer, built a CD-ROM-based home design application for selecting premium home design products for previewing in the context of images of any household rooms. \n\u2022 Built the prototype using Adobe Photoshop and [Macromedia Director](https://macromedia.fandom.com/wiki/Macromedia_Director).\n\u2022 Built the actual application using using [bash], [Linux], [Java] and [Marimba Bongo](https://www.thriftbooks.com/w/official-marimba-guide-to-bongo_danny-goodman/2574616/#edition=58026223&idiq=42367912) widget layout tool.\n\u2022 Updates for the self-updating application were delivered over the internet using [Marimba Castanet](https://www.infoworld.com/article/2076707/marimba-launches-new-castanet-with-a-less-java-centric-focus.html) push-technology."},{"role": "Ph.D. Media Arts & Science", "employer": "MIT Media Lab", "start": "1990-09-01", "end": "1997-04-01", "z-index": "2", "css name": "blue", "css RGB": "#0000ff", "css color": "", "text color": "#FFFFFF", "Description": "\u2022\tDoctor of Philosopy degree, [Massachusetts Institute of Technology]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/MIT-logo.png}, Cambridge, Massachusettes\n\u2022\tMedia Laboratory, Media Arts and Sciences\n\u2022\tTook courses in machine vision, signals and systems, digital signal processing, and stochastics.\n\u2022\tHelped build the operating system for the [Cheops multi-processor system](http://alumni.media.mit.edu/~wad/cheops_CSVT/cheops.html) used for digital video research and for holographic video\n\u2022\t[\u201cVision-assisted modeling for model-based video representations\u201d](https://dspace.mit.edu/handle/1721.1/29123), (Ph.D. Dissertation) MIT, Program in Media Arts & Sciences, 1997\n\u2022\t[\u201cSemiautomatic 3-D Model Extraction from Uncalibrated 2-D Camera Views.\u201d](https://www.media.mit.edu/publications/semiautomatic-3-d-model-extraction-from-uncalibrated-2-d-camera-views-2/) S. Becker & V. M. Bove, Jr., Proc. SPIE Image Synthesis, 2410, 1995, pp. 447-461.\n\u2022\t\u201cSemiautomatic Scene Modeling From 2-D Views with Partially Known Structure.\u201d Shawn Becker, MIT Media Lab Reports, 1995\n\u2022\t\u201cSemiautomatic Camera Lens Calibration from Partially Known Structure\u201d, Shawn Becker, MIT Media Lab Reports, 1994\n\u2022\t[\u201cFormulating a scene probability equation to differentiate the effects of shape & albedo on image brightness.\u201d](https://www.researchgate.net/publication/2668457_Formulating_a_Scene_Probability_Equation_to_Differentiate_the_Effects_of_Shape_and_Albedo_on_Image_Brightness) Shawn Becker, MIT Media Lab Reports, 1994\n\u2022\t\u201cComputation of some projective-chirplet-transform & metaplectic-chirplet-transform subspaces, with applications in image processing.\u201d Steve Mann & Shawn Becker, DSP World Symposium, Boston, Massachusetts, November 1992.\n\u2022 [C programming language], [TclTk], [X11], [HTML], [JavaScript],[CSS],[XMotif], [bash], [Linux]"},{"role": "MS Computer Science", "employer": "BYU", "start": "1987-09-01", "end": "1990-09-01", "z-index": "2", "css name": "mediumblue", "css RGB": "#0000cd", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 Masters of Science degree, [Brigham Young University]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-entrance-150x150.jpg}, Provo, Utah\nTook all courses required for both bachelors and masters degrees in Computer Science\n\u2022 Thesis project [\u201cInteractive Measurement of Three-Dimensional Objects Using a Depth Buffer & Linear Probe.\u201d](https://dl.acm.org/doi/pdf/10.1145/108360.108446) CS MS Thesis, Shawn Becker, William A. Barrett & Dan R. Olsen, ACM Transactions on Graphics, Vol. 10, No. 2, April 1991\n\u2022 Top Research Presentation \u2013 New Tech Research Conference - Brigham Young University \u2013 Provo, UT \u2013 March 1990\n\u2022 [\u201cFast Automated Object Detection Using Signature Parsing.\u201d](https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1192/1/Fast-Automated-Object-Detection-Using-Signature-Parsing/10.1117/12.969720.short) Tim Heaton; Shawn Becker; Kelley Anderson; William Barrett: Proceedings Volume 1192, Intelligent Robots & Computer Vision VIII: Algorithms & Techniques; (1990) https://doi.org/10.1117/12.969720\n\u2022 [\u201cProbabilistic Segmentation of Myocardial Tissue by Deterministic Relaxation.\u201d](https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1737&context=facpub) Jerome A. Broekhuijsen, Shawn C. Becker, & William A. Barrett: IEEE Proceedings of Computers in Cardiology, pp. 99-12, Jerusalem, September 1989.\n\u2022 [\u201cInteractive Measurement of three-Dimensional Cardiac Morphology.\u201d]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-MS-CS-Skull-Cross-Section-1.jpeg}(https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1736&context=facpub) Shawn C Becker, William A Barrett, October 1989, DOI: 10.1109/CIC.1989.130586, Conference: Computers in Cardiology.\n\u2022 [C programming language], [bash], [Linux], [XMotif], and [X11]."},{"role": "Full Stack Developer", "employer": "Cimmetrix LLC", "start": "1988-06-01", "end": "1989-09-01", "z-index": "3", "css name": "blueviolet", "css RGB": "#8a2be2", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 Front-end software developer of a reverse kinametics path planning system for multi-axis industrial robots for [Cimmetrix]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Cimetrix-PDF-combined-logo-150x100.png}.\n\u2022 Technologies used include [bash], [Linux], [C programming language], [bash](https://en.wikipedia.org/wiki/Bourne_shell), [X11] , [Xt toolkit intrinsics](https://en.wikipedia.org/wiki/X_Toolkit_Intrinsics), [Silicon Graphics Irix](https://en.wikipedia.org/wiki/Silicon_Graphics), and [HP-UX](https://en.wikipedia.org/wiki/HP-UX)."},{"role": "Project Manager / Technical Lead ", "employer": "MSC ", "start": "2007-12-01", "end": "2010-08-01", "z-index": "2", "css name": "yellow", "css RGB": "#ffff00", "css color": "", "text color": "#000000", "Description": "\u2022 MSC, now called [OneCall](https://onecallcm.com/), is a leading workers compensation services company. \n\u2022 As project manager and technical lead for this Sierra Vista Group project, I presented fixed schedule-fixed budget project proposals to C-level executives to add features to their legacy call center system used by 10 different healthcare divisions. \n\u2022 Interviewed stakeholders to create functional requirements and technical spefications for each stage of development.\n\u2022 Worked with development team to create work plan, assign tasks.\n\u2022 Oversaw quality assurance and customer approval testing.\n\u2022 Used the MS Office suite of business apps a well as MS Visio. "},{"role": "Senior Architect ", "employer": "Eleven LLC", "start": "2006-02-01", "end": "2007-12-01", "z-index": "2", "css name": "lime", "css RGB": "#00ff00", "css color": "", "text color": "#000000", "Description": "\u2022 [Eleven LLC](https://www.eleven.net/) built mobile apps used by beverage industry distributors to help manage placement of their products in the shelves and coolers in retail locations. The work done by the Sierra Vista Group was instrumental in their company being acquired by [Trimble Mobile Solutions](https://help.trimblegeospatial.com/TMM/Home.htm). \n\u2022 As the architect and team lead, we used [Java], [bash], [GitHub], [Linix], and [JBoss](https://developers.redhat.com/products/eap/overview) message-oriented middleware platform, [Sybase Anywhere](https://texas.gs.shi.com/Product/30451452/Sybase-SQL-Anywhere-Advanced-Edition) for the client/server based database, and [Windows Mobile](https://en.wikipedia.org/wiki/Windows_Mobile_5.0) running on ruggedized mobile devices. "},{"role": "Senior Architect", "employer": "Intrusic LLC", "start": "2005-02-01", "end": "2006-02-01", "z-index": "2", "css name": "limegreen", "css RGB": "#32cd32", "css color": "", "text color": "#000000", "Description": "\u2022 [Intrusic LLC](https://www.crunchbase.com/organization/intrusic) built real-time network monitoring systems that identified external and internal network intrusion attempts\n\u2022 As a Sierra Vista Group architech, I helped design and develop an approach for buffering live streaming network traffic for asynchronous package processing. \n\u2022 Used [Debian Linux](https://www.debian.org/), [C programming language](https://www.cprogramming.com/books/ritchie.html), and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software)."},{"role": "Project Manager / Technical Lead ", "employer": "AMI Entertainment ", "start": "2004-02-01", "end": "2005-02-01", "z-index": "2", "css name": "olivedrab", "css RGB": "#6b8e23", "css color": "", "text color": "#000000", "Description": "\u2022 AMI (https://amientertainment.com/) was the internet-music distribution incarnation of Rowe International. \n\u2022 As a Sierra Vista Group project manager and technical lead, I helped design and implement their system for making monthly ACH royalty payments to music copyright owners for mechanical and performance licensing rights.\n\u2022 Used [FileMaker Pro](https://www.claris.com/filemaker/), [bash], [Linux], [HTML], [CSS], [JavaScript], [Java], and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software)."},{"role": "Project Manager / Technical Lead ", "employer": "Rowe International", "start": "2003-03-01", "end": "2004-02-01", "z-index": "2", "css name": "forestgreen", "css RGB": "#228b22", "css color": "", "text color": "#000000", "Description": "\u2022 [Rowe International](https://pitchbook.com/profiles/company/13178-08) was the leading manufacturer of music jukeboxes. \n\u2022 Sierra Vista Group was consulted to assess their available technologies and create a plan to build their back-end systems to let them become a leading provider of internet-based music.\n\u2022 As project manager and technical lead created the project plan and led the development of a full-stack web application used by jukebox owners and Rowe sales and marketing.\n\u2022 Used [Java], [bash], [Linux], [HTML], [CSS], [JavaScript], [ObjectDesign](https://object.design/), [MySQL](https://www.mysql.com/), and [Adobe Photoshop](https://www.adobe.com/products/photoshop.html). \n"}] diff --git a/static_content/jobs/jobs.mjs b/static_content/jobs/jobs.mjs index dc0f603..f8f03ea 100644 --- a/static_content/jobs/jobs.mjs +++ b/static_content/jobs/jobs.mjs @@ -1 +1,249 @@ -const jobs = [{"role": "Consulting Data Engineer ", "employer": "The Cigna Group", "start": "2023-05-01", "end": "2023-12", "z-index": "3", "css name": "darkcyan", "css RGB": "#006688", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a consulting data engineer in the data cyber security team of the [Cigna Group](https://www.thecignagroup.com/) created a [REST API](url) using [Postman](https://www.postman.com/), [Linux], and [OpenAPI](https://openapi-generator.tech/) for pulling credentials from the [CyberArk identity security platform](https://www.cyberark.com/) using [mutual TLS SSL authentication](https://docs.solace.com/Security/Two-Way-SSL-Authentication.htm) with [AWS API Gateway](https://docs.aws.amazon.com/apigateway/). \n\u2022 Migrated a suite of legacy data pipeline [Python] elements running on the [Unity IoC platform](http://unitycontainer.org/articles/introduction.html) to pull credentials from the CyberArk service at runtime rather than using [Fernet](https://cryptography.io/en/latest/fernet/) encrypted local files. \n\u2022 Upgraded [GitHub] apps to use [CloudBees/Jenkins](https://docs.aws.amazon.com/apigateway/) CI/CD pipeline for build, applying sofware and cyber-secutity code checks, and on-prem server installation."},{"role": "Consulting Data Engineer ", "employer": "Warner Brothers Interactive Entertainment", "start": "2022-09-01", "end": "2023-05-01", "z-index": "2", "css name": "blue", "css RGB": "#0000ff", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a consulting data engineer in the analytics team of [Warner Brothers Interactive Entertainment](https://warnerbrosgames.com/) Division, I implemented high-volume pipeline integrations shuffling game telemetry and [user PII data] between WB-distributed consumer games and [marketing service platforms] via [Segment customer data platform](https://segment.com/customer-data-platform/) using [Kafka](https://aws.amazon.com/msk/), [Redshift](https://aws.amazon.com/redshift/), and [Apache Airflow](https://airflow.apache.org). \n\u2022 Employed [Python], [Linux], [Amazon Glue](https://aws.amazon.com/glue/) and [Apache Airflow](https://airflow.apache.org/) for external [3rd-party integrations] and internal [dev-ops integrations] with [Jenkins], [DataDog](https://www.datadoghq.com/), and [ZenDesk](https://zendesk.com) \n\u2022 Integrated with [Google BigQuery data warehouse](https://cloud.google.com/bigquery) and [AWS-managed services] [Apache Airflow](https://aws.amazon.com/managed-workflows-for-apache-airflow/), [S3], [AWS Glue](https://towardsdatascience.com/extract-transform-load-etl-aws-glue-edd383218cfd), and [AWS Redshift warehouse](https://aws.amazon.com/redshift/)."},{"role": "Consulting Data Engineer ", "employer": "Angel Studios ", "start": "2021-11-01", "end": "2022-09-01", "z-index": "1", "css name": "mediumblue", "css RGB": "#4400cd", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a consulting data engineer for [Angel Studios](https://www.angel.com/home], a streaming media service that offers family-friendly entertainment that amplifies light, with titles including The Chosen, Dry Bar Comedy, and Tuttle Twins.\n\u2022 Used [Python], [Pandas], [Numpy], [Keras], [Linux], and [Jupyter](https://jupyter.org/) to build and tune hyperparameters of a [convolutional neural network](https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53) with [supervised learning] on [AWS Sagemaker](https://aws.amazon.com/pm/sagemaker/) to classify movie frames from episodic programs stored in [Amazon S3](https://aws.amazon.com/s3/storage-classes). \n\u2022 Built web client apps using [Python] with [Postman](https://www.postman.com/) that made [RESTful API] requests to pull monthly usage data from various web marketing partners like [FaceBook Marketing](https://www.quora.com/What-is-Facebook-Marketing-1), [Google Play](https://play.google/howplayworks/) , and [Vimeo](https://vimeo.com/). \n\u2022 Worked with [Segment customer data platform](https://segment.com/customer-data-platform/), [Excel], and [Tableau] to create scheduled reports for the company's sales and finance teams."},{"role": "Consulting Data Engineer ", "employer": "Greenseed Tech", "start": "2020-11-01", "end": "2021-11-01", "z-index": "2", "css name": "blueviolet", "css RGB": "#8a2be2", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a consulting data engineer for Greenseed Tech, an internet company that provides daily lead reports for independent real-estage agents world-wide, I [containerized] legacy web applications using [Linux], [Docker](https://www.docker.com/) and [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/). \n\u2022 Documented existing data architecture as [ERDs](https://www.lucidchart.com/pages/er-diagrams) using [DBeaver Enterprise](https://dbeaver.com/dbeaver-enterprise/). "},{"role": "Consulting Full-Stack Developer ", "employer": "NuSkin", "start": "2019-11-01", "end": "2020-11-01", "z-index": "1", "css name": "purple", "css RGB": "#800080", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a consulting front-end software developer for [NuSkin](https://www.nuskin.com/us/en/, an international company known for its excellent skin and beauty products I created new [Vue.js](https://vuejs.org/), [Nuxt](https://nuxt.com/), and [Vuetify](https://vuetifyjs.com/en/) components using [Linux], [NodeJS] and [SCSS]. \n\u2022 Internationalized content using [Adobe Experience Cloud](https://business.adobe.com/)."},{"role": "Senior Data Engineer ", "employer": "SeniorLink", "start": "2017-03-01", "end": "2019-11-01", "z-index": "2", "css name": "maroon", "css RGB": "#800000", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a senior data engineer for SeniorLink's [Vela project]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Vela-150x126.png} a homeservices support platform, helped create [ETL](https://aws.amazon.com/what-is/etl/) processes using [AWS Kinesis](https://aws.amazon.com/pm/kinesis/), [Python], [PySpark](https://spark.apache.org/), and [AWS Data Pipeline](https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/what-is-datapipeline.html) to load structured event data from [PostgreSQL] databases into a centralized [Redshift warehouse](https://aws.amazon.com/pm/redshift/). \n\u2022 Saved data as [self-describing data assets] in [S3] using [AWS Kinesis] and [AWS Lambda](https://docs.aws.amazon.com/lambda/) to aggregate event data into [schema-on-read] file formats, [Apache Avro](https://avro.apache.org/), and [Apache Parquet](https://parquet.apache.org/).\n\u2022 Steered efforts in creating a [Data Lake](https://aws.amazon.com/big-data/datalakes-and-analytics/datalakes/) using [PostgreSQL](url) and [FlyWay](https://flywaydb.org/) with [Python](url) and [PySpark](https://spark.apache.org/docs/latest/api/python/index.html) pre-processing on [EC2 instances](url) with [AWS EFS](https://zesty.co/blog/ebs-vs-efs-which-is-right), [EBS], and [S3] storage.\n\u2022 Used streaming event messages queued in [RabbitMQ](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/working-with-rabbitmq.html) and [AWS Kinesis] to build [type-2 slowly changing dimensions]](url) and accumulative facts tables. \n\u2022 Designed and implemented a custom [star-schema warehouse](https://www.databricks.com/glossary/star-schema) and [ETL] processes to [de-normalize](https://en.wikipedia.org/wiki/Denormalization) and load data into an [AWS Redshift](https://aws.amazon.com/redshift/) data warehouse for BI reporting using [Tableau](https://www.tableau.com/).\n\u2022 [Test-driven development](https://www.pluralsight.com/blog/software-development/tdd-vs-bdd) using [Linux], [Python], [PyCharm], [PyTest], [Unit-test], [GitHub], [Jira], and [Jenkins CI/CD](https://www.jenkins.io/)."},{"role": "Consulting Back-End Engineer ", "employer": "BigR.io", "start": "2016-12-01", "end": "2017-03-01", "z-index": "1", "css name": "crimson", "css RGB": "#dc143c", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As a consulting back-end software developer at [BigR.io]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Bigr.io_-150x106.png} I used [AWS microservices] for custom voice-based [natural language processing] applications.\n\u2022 Used [Apache ActiveMQ](https://activemq.apache.org/), [Swagger](https://swagger.io/), [JSON], [Jackson](url), [AOP](https://www.baeldung.com/spring-aop), [Eclipse], [Maven], [Git], [Jira], and [Jenkins CI/CD].\n\u2022 [Java], [J2EE], [Servlets], [Spring], [SpringBoot], [JAX-RS], [Linux], [JUnit], [JMeter], and [JProfile]"},{"role": "Software Architect / Co-Founder ", "employer": "ClipFile LLC", "start": "2011-02-01", "end": "2016-12-01", "z-index": "2", "css name": "orangered", "css RGB": "#ff4500", "css color": "", "text color": "#000000", "Description": "\u2022 Co-founded [ClipFile]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/clipfile-infrastructure-150x150.png}, a company that envisioned building a web destination where users could easily record and share their favorite pieces of content like facts, authored stories, quotes, articles, chapters, or personal thoughts, as a way of concretely defining their personal [mindset]{https://sourcesofinsight.com/wp-content/uploads/2014/04/Mindset-768x505.jpg}(https://sourcesofinsight.com/what-is-mindset/).\n\u2022 Implemented [fuzzy matching](https://nanonets.com/blog/fuzzy-matching-fuzzy-logic/), [word clustering](https://www.ilc.cnr.it/EAGLES96/rep2/node37.html#:~:text=Word%20clustering%20is%20a%20technique,to%20information%20retrieval%20and%20filtering.), [semantic similarity scores](https://towardsdatascience.com/semantic-similarity-using-transformers-8f3cb5bf66d6), and [collaborative filtering](https://www.hindawi.com/journals/aai/2009/421425/) to help users find content that matched or differed from thieir own mindset.\n\u2022 Launched a novel [SaaS] using [Amazon Web Services] that let individuals and content creators search and share [mindsets].\n\u2022 Conceptualized patented technology by designing and implementing a fuil-stack consumer-facing content management system that supported tuned matching among selected attributes.\n\u2022 [Java], [J2EE], [JSP], [Servlets], [Spring], [AWS services], [JavaScript], [JQuery], [HTML5], [CSS], [JUnit], [JMeter], [JProfile].\n\u2022 Utilized [REST], [Swagger], [Apache Shiro](https://shiro.apache.org/), [Eclipse IDE](https://www.eclipse.org/home/whatis/), [Apache Maven](https://maven.apache.org/what-is-maven.html), [Apache Ant](https://ant.apache.org/), [Git], [Hibernate], [AWS SimpleDB](https://aws.amazon.com/simpledb/), [CentOS Linux](https://www.centos.org/), [Apache Tomcat](https://tomcat.apache.org/), [Linux], [Jetty](https://projects.eclipse.org/projects/rt.jetty), and [Spring MVC](https://docs.spring.io/spring-framework/reference/web/webmvc.html).\n\u2022 Served as co-founder and co-authored [four patents](https://www.freepatentsonline.com/y2013/0325870.html)."},{"role": "Software Architect / Co-Founder ", "employer": "Sierra Vista Group LLC", "start": "2002-11-01", "end": "2011-02-01", "z-index": "1", "css name": "orange", "css RGB": "#ffa500", "css color": "", "text color": "#000000", "Description": "\u2022 Co-founded a finance and technology boutique called [Sierra Vista Group](https://6sense.com/company/sierra-vista-group-llc/5ba8a5247c8666394376fc4f) that delivered support in planning and proposing effective IT strategies for key clients in several industries. \n\u2022 Performed various services, including system and architecture assessment and solutions design, to ensure the smooth running of technical projects.\n\u2022 Managed project schedules and technical specifications to match business requirements within contractual budget constraints. \n\u2022 Identified opportunities for potential clients requiring expertise in product development, software engineering, and data modeling. Negotiated and communicated with c-level client management regarding project milestone agreements.\n\u2022 Increased ROI for each client\u2019s project by hiring and managing contractors to deliver custom software solutions.\n\u2022 Delivered high-level leadership and guidance to a team of software engineering consultants for several projects to accelerate operational excellence."},{"role": "Software Architect / Co-Founder ", "employer": "HomePorfolio LLC ", "start": "1998-02-01", "end": "2002-11-01", "z-index": "1", "css name": "teal", "css RGB": "#008080", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As co-founder and CTO, designed and led the development of a public website used by discerning home designers and builders called [HomePortfolio.com](https://homeportfolio.com/). \n\u2022 Hired a staff of 10 software and databases developers. \n\u2022 Worked with data acquisition team to scan and tag over 700,000 premium home design products from over 2,000 manufactures and vendors.\n\u2022 Designed datamodel and data entry tools for category-specific product attribution. \n\u2022 Helped extended the business model to provide online product selection tools for participating vendors and manufacturers.\n\u2022 Instrumental in raising over $70M in venture capital. \n\u2022 Used [Oracle], [ATG Dyanamo]( https://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGPersBusinessGuide/html/s0102dynamoapplicationframework01.html), [Java], [Akamai]{https://www.hiclipart.com/free-transparent-background-png-clipart-zkmsn}(https://www.akamai.com/), [WebTrends](https://www.webtrends.com/), [FileMakerPro], [ImageMagik](https://imagemagick.org/index.php), [Linux], and [Omnigraffle](https://www.omnigroup.com/omnigraffle) for data modeling and workflow designs."},{"role": "Lead Software Developer ", "employer": "BuildingBlocks LLC ", "start": "1996-06-01", "end": "1998-02-01", "z-index": "1", "css name": "darkcyan", "css RGB": "#008b8b", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 As lead software developer, built a CD-ROM-based home design application for selecting premium home design products for previewing in the context of images of any household rooms. \n\u2022 Built the prototype using Adobe Photoshop and [Macromedia Director](https://macromedia.fandom.com/wiki/Macromedia_Director).\n\u2022 Built the actual application using using [Linux], [Java] and [Marimba Bongo](https://www.thriftbooks.com/w/official-marimba-guide-to-bongo_danny-goodman/2574616/#edition=58026223&idiq=42367912) widget layout tool.\n\u2022 Updates for the self-updating application were delivered over the internet using [Mariba Castanet](https://www.infoworld.com/article/2076707/marimba-launches-new-castanet-with-a-less-java-centric-focus.html) push-technology."},{"role": "Ph.D. Media Arts & Science", "employer": "MIT Media Lab", "start": "1990-09-01", "end": "1997-04-01", "z-index": "2", "css name": "blue", "css RGB": "#0000ff", "css color": "", "text color": "#FFFFFF", "Description": "\u2022\tDoctor of Philosopy degree, [Massachusetts Institute of Technology]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/MIT-logo.png}, Cambridge, Massachusettes\n\u2022\tMedia Laboratory, Media Arts and Sciences\n\u2022\tTook courses in machine vision, signals and systems, digital signal processing, and stochastics.\n\u2022\tHelped build the operating system for the [Cheops multi-processor system](http://alumni.media.mit.edu/~wad/cheops_CSVT/cheops.html) used for digital video research and for holographic video\n\u2022\t[\u201cVision-assisted modeling for model-based video representations\u201d](https://dspace.mit.edu/handle/1721.1/29123), (Ph.D. Dissertation) MIT, Program in Media Arts & Sciences, 1997\n\u2022\t[\u201cSemiautomatic 3-D Model Extraction from Uncalibrated 2-D Camera Views.\u201d](https://www.media.mit.edu/publications/semiautomatic-3-d-model-extraction-from-uncalibrated-2-d-camera-views-2/) S. Becker & V. M. Bove, Jr., Proc. SPIE Image Synthesis, 2410, 1995, pp. 447-461.\n\u2022\t\u201cSemiautomatic Scene Modeling From 2-D Views with Partially Known Structure.\u201d Shawn Becker, MIT Media Lab Reports, 1995\n\u2022\t\u201cSemiautomatic Camera Lens Calibration from Partially Known Structure\u201d, Shawn Becker, MIT Media Lab Reports, 1994\n\u2022\t[\u201cFormulating a scene probability equation to differentiate the effects of shape & albedo on image brightness.\u201d](https://www.researchgate.net/publication/2668457_Formulating_a_Scene_Probability_Equation_to_Differentiate_the_Effects_of_Shape_and_Albedo_on_Image_Brightness) Shawn Becker, MIT Media Lab Reports, 1994\n\u2022\t\u201cComputation of some projective-chirplet-transform & metaplectic-chirplet-transform subspaces, with applications in image processing.\u201d Steve Mann & Shawn Becker, DSP World Symposium, Boston, Massachusetts, November 1992.\n\u2022 [C programming language], [TclTk], [X11], [XMotif], [Linux]"},{"role": "MS Computer Science", "employer": "BYU", "start": "1987-09-01", "end": "1990-09-01", "z-index": "2", "css name": "mediumblue", "css RGB": "#0000cd", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 Masters of Science degree, [Brigham Young University]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-entrance-150x150.jpg}, Provo, Utah\nTook all courses required for both bachelors and masters degrees in Computer Science\n\u2022 Thesis project [\u201cInteractive Measurement of Three-Dimensional Objects Using a Depth Buffer & Linear Probe.\u201d](https://dl.acm.org/doi/pdf/10.1145/108360.108446) CS MS Thesis, Shawn Becker, William A. Barrett & Dan R. Olsen, ACM Transactions on Graphics, Vol. 10, No. 2, April 1991\n\u2022 Top Research Presentation \u2013 New Tech Research Conference - Brigham Young University \u2013 Provo, UT \u2013 March 1990\n\u2022 [\u201cFast Automated Object Detection Using Signature Parsing.\u201d](https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1192/1/Fast-Automated-Object-Detection-Using-Signature-Parsing/10.1117/12.969720.short) Tim Heaton; Shawn Becker; Kelley Anderson; William Barrett: Proceedings Volume 1192, Intelligent Robots & Computer Vision VIII: Algorithms & Techniques; (1990) https://doi.org/10.1117/12.969720\n\u2022 [\u201cProbabilistic Segmentation of Myocardial Tissue by Deterministic Relaxation.\u201d](https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1737&context=facpub) Jerome A. Broekhuijsen, Shawn C. Becker, & William A. Barrett: IEEE Proceedings of Computers in Cardiology, pp. 99-12, Jerusalem, September 1989.\n\u2022 [\u201cInteractive Measurement of three-Dimensional Cardiac Morphology.\u201d]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-MS-CS-Skull-Cross-Section-1.jpeg}(https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1736&context=facpub) Shawn C Becker, William A Barrett, October 1989, DOI: 10.1109/CIC.1989.130586, Conference: Computers in Cardiology.\n\u2022 [C programming language], [Linux], [XMotif], and [X11]."},{"role": "Software Developer", "employer": "Cimmetrix LLC", "start": "1988-06-01", "end": "1989-09-01", "z-index": "3", "css name": "blueviolet", "css RGB": "#8a2be2", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 Front-end software developer of a reverse kinametics path planning system for multi-axis industrial robots for [Cimmetrix]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Cimetrix-PDF-combined-logo-150x100.png}.\n\u2022 Technologies used include [Linux], [C programming language], [Borne shell](https://en.wikipedia.org/wiki/Bourne_shell), [X11] , [Xt toolkit intrinsics](https://en.wikipedia.org/wiki/X_Toolkit_Intrinsics), [Silicon Graphics Irix](https://en.wikipedia.org/wiki/Silicon_Graphics), and [HP-UX](https://en.wikipedia.org/wiki/HP-UX)."},{"role": "BS Design Engineering Technology", "employer": "BYU", "start": "1984-09-01", "end": "1987-09-01", "z-index": "2", "css name": "purple", "css RGB": "#800080", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 Completed bachelor degree in Design Engineering Technologies\n\u2022 Drafting, CAD/CAM, machine design, fluid dynamics, ferrous metallurgy, static load bearing mathematics."},{"role": "Call Center Reservationist", "employer": "Dell Webb Properties", "start": "1984-01-01", "end": "1984-09-01", "z-index": "1", "css name": "maroon", "css RGB": "#800000", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 Worked as a reservations agent for Dell Webb resorts and [houseboat rentals]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Del-Webb-Reservations-150x115.png}(https://www.lake-powell-country.com/lake-powell-houseboat-history.html) at the various marinas url on [Lake Powell](https://www.lakepowell.com/) in Utah"},{"role": "Missonary", "employer": "Taiwan Taibei Mission", "start": "1982-07-01", "end": "1984-01-01", "z-index": "3", "css name": "crimson", "css RGB": "#dc143c", "css color": "", "text color": "#FFFFFF", "Description": "\u2022 Served as a missionary for the Church of Jesus Christ of Latter-day Saints in the [Taiwan Taibei mission](https://www.mymission.com/lds-missions/taiwan-taipei-mission).\n\u2022 Served as branch president in the town [Yuli](https://en.wikivoyage.org/wiki/Yuli) in the Hualien County on the east coast of Taiwan."},{"role": "BS GED", "employer": "BYU", "start": "1981-09-01", "end": "1982-07-01", "z-index": "2", "css name": "orangered", "css RGB": "#ff4500", "css color": "", "text color": "#000000", "Description": "\u2022 Majored in mathematics, took general education required classes as well as design and oil painting."},{"role": "Data Processing", "employer": "Greyhound Corp", "start": "1981-04-01", "end": "1981-09-01", "z-index": "1", "css name": "orange", "css RGB": "#ffa500", "css color": "", "text color": "#000000", "Description": "\u2022 Worked as an intern in the Pension Department at [Greyhound Corporate]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Greyhound-Corporation-Phoenix-Downtown-circa-1970-150x150.png}.\n\u2022 Manully sorted thousands of pension checks and doing handwriting comparisons to find fraudulent cashing of checks for deceased pensioners."},{"role": "Newspaper Delivery", "employer": "Arizona Republic", "start": "1977-09-01", "end": "1981-04-01", "z-index": "1", "css name": "gold", "css RGB": "#ffd700", "css color": "", "text color": "#000000", "Description": "\u2022 Seven-day paper delivery for the [Arizona Republic Newspaper]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/AZ-Republic-newspaper-150x150.jpg}.\n\u2022 Weekly collections\n\u2022 Used [purple Schwinn banana seat]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/AZ-Republic-paper-delivery-vehical-150x150.png}, [Schwinn 10 speed](url)."},{"role": "Project Manager / Technical Lead ", "employer": "MSC ", "start": "2007-12-01", "end": "2010-08-01", "z-index": "2", "css name": "yellow", "css RGB": "#ffff00", "css color": "", "text color": "#000000", "Description": "\u2022 MSC, now called [OneCall](https://onecallcm.com/), is a leading workers compensation services company. \n\u2022 As project manager and technical lead for this Sierra Vista Group project, I presented fixed schedule-fixed budget project proposals to C-level executives to add features to their legacy call center system used by 10 different healthcare divisions. \n\u2022 Interviewed stakeholders to create functional requirements and technical spefications for each stage of development.\n\u2022 Worked with development team to create work plan, assign tasks.\n\u2022 Oversaw quality assurance and customer approval testing.\n\u2022 Used the MS Office suite of business apps a well as MS Visio. "},{"role": "Consulting Architect ", "employer": "Eleven LLC", "start": "2006-02-01", "end": "2007-12-01", "z-index": "2", "css name": "lime", "css RGB": "#00ff00", "css color": "", "text color": "#000000", "Description": "\u2022 [Eleven LLC](https://www.eleven.net/) built mobile apps used by beverage industry distributors to help manage placement of their products in the shelves and coolers in retail locations. The work done by the Sierra Vista Group was instrumental in their company being acquired by [Trimble Mobile Solutions](https://help.trimblegeospatial.com/TMM/Home.htm). \n\u2022 As the consulting architect and team lead, we used [Java], [Linix], and [JBoss](https://developers.redhat.com/products/eap/overview) message-oriented middleware platform, [Sybase Anywhere](https://texas.gs.shi.com/Product/30451452/Sybase-SQL-Anywhere-Advanced-Edition) for the client/server based database, and [Windows Mobile 5](https://en.wikipedia.org/wiki/Windows_Mobile_5.0) running on ruggedized mobile devices. "},{"role": "Consulting Architect", "employer": "Intrusic LLC", "start": "2005-02-01", "end": "2006-02-01", "z-index": "2", "css name": "limegreen", "css RGB": "#32cd32", "css color": "", "text color": "#000000", "Description": "\u2022 [Intrusic LLC](https://www.crunchbase.com/organization/intrusic) built real-time network monitoring systems that identified external and internal network intrusion attempts\n\u2022 As a Sierra Vista Group consulting architech, I helped design and develop an approach for buffering live streaming network traffic for asynchronous package processing. \n\u2022 Used [Debian Linux](https://www.debian.org/), [C programming language](https://www.cprogramming.com/books/ritchie.html), and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software)."},{"role": "Consulting Architect / Technical Lead ", "employer": "AMI Entertainment ", "start": "2004-02-01", "end": "2005-02-01", "z-index": "2", "css name": "olivedrab", "css RGB": "#6b8e23", "css color": "", "text color": "#000000", "Description": "\u2022 AMI (https://amientertainment.com/) was the internet-music distribution incarnation of Rowe International. \n\u2022 As a Sierra Vista Group consulting architect and technical lead, I helped design and implement their system for making monthly ACH royalty payments to music copyright owners for mechanical and performance licensing rights.\n\u2022 Used [FileMaker Pro](https://www.claris.com/filemaker/), [Linux], [Java5], and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software)."},{"role": "Consulting Architect / Technical Lead ", "employer": "Rowe International", "start": "2003-03-01", "end": "2004-02-01", "z-index": "2", "css name": "forestgreen", "css RGB": "#228b22", "css color": "", "text color": "#000000", "Description": "\u2022 [Rowe International](https://pitchbook.com/profiles/company/13178-08) was the leading manufacturer of music jukeboxes. \n\u2022 Sierra Vista Group was consulted to assess their available technologies and create a plan to build their back-end systems to let them become a leading provider of internet-based music.\n\u2022 As consulting architect and technical lead created the project plan and led the development of a full-stack web application used by jukebox owners and Rowe sales and marketing.\n\u2022 Used [Java], [Linux], [ObjectDesign](https://object.design/), JavaScript , [MySQL](https://www.mysql.com/), and [Adobe Photoshop](https://www.adobe.com/products/photoshop.html). \n"}]; +const jobs = [ + { + role: "Senior Data Engineer ", + employer: "The Cigna Group", + start: "2023-05-01", + end: "2024-01-01", + "z-index": "3", + "css name": "darkcyan", + "css RGB": "#006688", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As a senior data engineer in the data cyber security team of the [Cigna Group](https://www.thecignagroup.com/) created a [REST API](url) using [Postman](https://www.postman.com/), [bash], [Linux], and [OpenAPI](https://openapi-generator.tech/) for pulling credentials from the [CyberArk identity security platform](https://www.cyberark.com/) using [mutual TLS SSL authentication](https://docs.solace.com/Security/Two-Way-SSL-Authentication.htm) with [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/). \n\u2022 Migrated a suite of legacy data pipeline [Python] elements running on the [Unity IoC platform](http://unitycontainer.org/articles/introduction.html) to pull credentials from the CyberArk service at runtime rather than using [Fernet](https://cryptography.io/en/latest/fernet/) encrypted local files. \n\u2022 Upgraded [GitHub] apps to use [Jenkins](https://docs.aws.amazon.com/apigateway/) CI/CD pipeline for build, applying sofware and cyber-secutity code checks, and on-prem server installation.", + }, + { + role: "Senior Data Engineer ", + employer: "Warner Brothers Interactive Entertainment", + start: "2022-09-01", + end: "2023-05-01", + "z-index": "2", + "css name": "blue", + "css RGB": "#0000ff", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As a senior data engineer in the analytics team of [Warner Brothers Interactive Entertainment](https://warnerbrosgames.com/) Division, I implemented high-volume pipeline integrations shuffling game telemetry and [user PII data] between WB-distributed consumer games and [marketing service platforms] via [Segment customer data platform](https://segment.com/customer-data-platform/) using [Kafka](https://aws.amazon.com/msk/), [Amazon Redshift](https://aws.amazon.com/redshift/), and [Apache Airflow](https://airflow.apache.org). \n\u2022 Employed [Python], [GitHub], [bash], [Linux], [Amazon Glue](https://aws.amazon.com/glue/) and [Apache Airflow](https://airflow.apache.org/) for external 3rd-party integrations and internal dev-ops integrations with [Jenkins], [DataDog](https://www.datadoghq.com/), and [ZenDesk](https://zendesk.com) \n\u2022 Integrated with [Google BigQuery data warehouse](https://cloud.google.com/bigquery using [Apache Airflow](https://aws.amazon.com/managed-workflows-for-apache-airflow/), [Amazon S3], and [Amazon Redshift](https://aws.amazon.com/redshift/).", + }, + { + role: "Senior Data Engineer ", + employer: "Angel Studios ", + start: "2021-11-01", + end: "2022-09-01", + "z-index": "1", + "css name": "mediumblue", + "css RGB": "#4400cd", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As a senior data engineer for [Angel Studios](https://www.angel.com/home), a streaming media service that offers family-friendly entertainment that amplifies light, with titles including The Chosen, Dry Bar Comedy, and Tuttle Twins.\n\u2022 Used [Python], [GitHub], [Pandas], [Numpy], [Keras], [bash], [Linux], and [Jupyter](https://jupyter.org/) to build and tune hyperparameters of a [convolutional neural network](https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53) with [supervised learning] on [Amazon Sagemaker](https://aws.amazon.com/pm/sagemaker/) to classify movie frames from episodic programs stored in [Amazon S3](https://aws.amazon.com/s3/storage-classes). \n\u2022 Built web client apps using [Python] with [Postman](https://www.postman.com/) that made [REST API] requests to pull monthly usage data from various web marketing partners like [FaceBook Marketing](https://www.quora.com/What-is-Facebook-Marketing-1), [Google Play](https://play.google/howplayworks/) , and [Vimeo](https://vimeo.com/). \n\u2022 Worked with [Segment customer data platform](https://segment.com/customer-data-platform/), [Excel], and [Tableau] to create scheduled reports for the company's sales and finance teams.", + }, + { + role: "Senior Data Engineer ", + employer: "Greenseed Tech", + start: "2020-11-01", + end: "2021-11-01", + "z-index": "2", + "css name": "blueviolet", + "css RGB": "#8a2be2", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As a senior software engineer for Greenseed Tech, an internet company that provides daily lead reports for independent real-estage agents world-wide, I [containerized] legacy web applications using [bash], [Linux], [GitHub], [Docker](https://www.docker.com/) and [Amazon Secrets Manager](https://aws.amazon.com/secrets-manager/). \n\u2022 Updated legacy web apps using [bash], [Linux], [HTML], [CSS], [JavaScript], [NGINX], and [OpenSSL].\n\u2022 Documented existing data architecture as [ERDs](https://www.lucidchart.com/pages/er-diagrams) using [DBeaver Enterprise](https://dbeaver.com/dbeaver-enterprise/). ", + }, + { + role: "Senior Full-Stack Developer ", + employer: "NuSkin", + start: "2019-11-01", + end: "2020-11-01", + "z-index": "1", + "css name": "purple", + "css RGB": "#800080", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As a senior full stack developer for [NuSkin](https://www.nuskin.com/us/en/, an international company known for its excellent skin and beauty products I created new [Vue.js](https://vuejs.org/), [Nuxt](https://nuxt.com/), and [Vuetify](https://vuetifyjs.com/en/) components using [bash], [Linux], [GitHub], [NodeJS], [HTML] and [CSS]. \n\u2022 Internationalized content using [Adobe Experience Cloud](https://business.adobe.com/).", + }, + { + role: "Senior Data Engineer ", + employer: "SeniorLink", + start: "2017-03-01", + end: "2019-11-01", + "z-index": "2", + "css name": "maroon", + "css RGB": "#800000", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As a senior data engineer for SeniorLink's [Vela project]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Vela-150x126.png} a homeservices support platform, helped create [ETL](https://aws.amazon.com/what-is/etl/) processes using [Amazon Kinesis](https://aws.amazon.com/pm/kinesis/), [Python], [PySpark](https://spark.apache.org/), and [Amazon Data Pipeline](https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/what-is-datapipeline.html) to load structured event data from [PostgreSQL] databases into [Amazon Redshift](https://aws.amazon.com/pm/redshift/). \n\u2022 Saved data to [Amazon S3] using [Amazon Kinesis] and triggered [Amazon Lambda](https://docs.aws.amazon.com/lambda/) jobs to aggregate steaming event data into [schema-on-read] file formats, [Apache Avro](https://avro.apache.org/) and [Apache Parquet](https://parquet.apache.org/).\n\u2022 Steered efforts in creating a [Data Lake](https://aws.amazon.com/big-data/datalakes-and-analytics/datalakes/) using [PostgreSQL] and [FlyWay](https://flywaydb.org/) with [Python] and [PySpark](https://spark.apache.org/docs/latest/api/python/index.html) pre-processing on [EC2 instances] using shared [Amazon EFS](https://zesty.co/blog/ebs-vs-efs-which-is-right) for staged storage.\n\u2022 Used streaming event messages queued in [RabbitMQ](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/working-with-rabbitmq.html) and [Amazon Kinesis] to build [type-2 slowly changing dimensions] and accumulative facts tables. \n\u2022 Designed and implemented a custom [star-schema warehouse](https://www.databricks.com/glossary/star-schema) and [ETL] processes to [de-normalize](https://en.wikipedia.org/wiki/Denormalization) and load data into [Amazon Redshift](https://aws.amazon.com/redshift/) data warehouse for BI reporting using [Tableau](https://www.tableau.com/).\n\u2022 [Test-driven development](https://www.pluralsight.com/blog/software-development/tdd-vs-bdd) using [bash], [Linux], [Python], [PyCharm], [PyTest], [Unit-test], [GitHub], [Jira], and [Jenkins](https://www.jenkins.io/).", + }, + { + role: "Senior Back-End Engineer ", + employer: "BigR.io", + start: "2016-12-01", + end: "2017-03-01", + "z-index": "1", + "css name": "crimson", + "css RGB": "#dc143c", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As a senior software engineer at [BigR.io]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Bigr.io_-150x106.png} I used [Amazon microservices] for custom voice-based [natural language processing] applications.\n\u2022 Used [Apache ActiveMQ](https://activemq.apache.org/), [Swagger](https://swagger.io/), [JSON], [Jackson](url), [AOP](https://www.baeldung.com/spring-aop), [Eclipse], [Maven], [GitHub], [Jira], and [Jenkins].\n\u2022 [Java], [J2EE], [Servlets], [Spring], [SpringBoot], [JAX-RS], [bash], [Linux], [JUnit], [JMeter], and [JProfile]", + }, + { + role: "Technical Lead / Co-Founder ", + employer: "ClipFile LLC", + start: "2011-02-01", + end: "2016-12-01", + "z-index": "2", + "css name": "orangered", + "css RGB": "#ff4500", + "css color": "", + "text color": "#000000", + Description: + "\u2022 Co-founded [ClipFile]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/clipfile-infrastructure-150x150.png}, a company that envisioned building a web destination where users could easily record and share their favorite pieces of content like facts, authored stories, quotes, articles, chapters, or personal thoughts, as a way of concretely defining their personal [mindset]{https://sourcesofinsight.com/wp-content/uploads/2014/04/Mindset-768x505.jpg}(https://sourcesofinsight.com/what-is-mindset/).\n\u2022 Implemented [fuzzy matching](https://nanonets.com/blog/fuzzy-matching-fuzzy-logic/), [word clustering](https://www.ilc.cnr.it/EAGLES96/rep2/node37.html#:~:text=Word%20clustering%20is%20a%20technique,to%20information%20retrieval%20and%20filtering.), [semantic similarity scores](https://towardsdatascience.com/semantic-similarity-using-transformers-8f3cb5bf66d6), and [collaborative filtering](https://www.hindawi.com/journals/aai/2009/421425/) to help users find content that matched or differed from thieir own mindset.\n\u2022 Launched a novel [SaaS] using [Amazon Web Services] that let individuals and content creators search and share mindsets.\n\u2022 Conceptualized patented technology by designing and implementing a fuil-stack consumer-facing content management system that supported tuned matching among selected attributes.\n\u2022 [Java], [J2EE], [JSP], [Servlets], [Spring], [Amazon services], [JavaScript], [JQuery], [HTML], [CSS], [JUnit], [JMeter], [JProfile].\n\u2022 Utilized [REST API], [Swagger], [Apache Shiro](https://shiro.apache.org/), [Eclipse IDE](https://www.eclipse.org/home/whatis/), [Apache Maven](https://maven.apache.org/what-is-maven.html), [Apache Ant](https://ant.apache.org/), [GitHub], [Hibernate], [Amazon SimpleDB](https://aws.amazon.com/simpledb/), [CentOS Linux](https://www.centos.org/), [Apache Tomcat](https://tomcat.apache.org/), [bash], [Linux], [Jetty](https://projects.eclipse.org/projects/rt.jetty), and [Spring MVC](https://docs.spring.io/spring-framework/reference/web/webmvc.html).\n\u2022 Served as co-founder and co-authored [four patents](https://www.freepatentsonline.com/y2013/0325870.html).", + }, + { + role: "Lead Solutions Architect / Co-Founder ", + employer: "Sierra Vista Group LLC", + start: "2002-11-01", + end: "2011-02-01", + "z-index": "1", + "css name": "orange", + "css RGB": "#ffa500", + "css color": "", + "text color": "#000000", + Description: + "\u2022 Co-founded a finance and technology boutique called [Sierra Vista Group](https://6sense.com/company/sierra-vista-group-llc/5ba8a5247c8666394376fc4f) that delivered support in planning and proposing effective IT strategies for key clients in several industries. \n\u2022 Performed various services, including system and architecture assessment and solutions design, to ensure the smooth running of technical projects.\n\u2022 Managed project schedules and technical specifications to match business requirements within contractual budget constraints. \n\u2022 Identified opportunities for potential clients requiring expertise in product development, software engineering, and data modeling. Negotiated and communicated with c-level client management regarding project milestone agreements.\n\u2022 Increased ROI for each client\u2019s project by hiring and managing contractors to deliver custom software solutions.\n\u2022 Delivered high-level leadership and guidance to a team of software engineering consultants for several projects to accelerate operational excellence.", + }, + { + role: "Technical Lead / Co-Founder ", + employer: "HomePorfolio LLC ", + start: "1998-02-01", + end: "2002-11-01", + "z-index": "1", + "css name": "teal", + "css RGB": "#008080", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As co-founder and CTO, designed and led the development of a public website used by discerning home designers and builders called [HomePortfolio.com](https://homeportfolio.com/). \n\u2022 Hired a staff of 10 software and databases developers. \n\u2022 Worked with data acquisition team to scan and tag over 700,000 premium home design products from over 2,000 manufactures and vendors.\n\u2022 Designed datamodel and data entry tools for category-specific product attribution. \n\u2022 Helped extended the business model to provide online product selection tools for participating vendors and manufacturers.\n\u2022 Instrumental in raising over $70M in venture capital. \n\u2022 Used [Oracle], [ATG Dyanamo]( https://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGPersBusinessGuide/html/s0102dynamoapplicationframework01.html), [Java], [Akamai]{https://www.hiclipart.com/free-transparent-background-png-clipart-zkmsn}(https://www.akamai.com/), [WebTrends](https://www.webtrends.com/), [FileMakerPro], [ImageMagik](https://imagemagick.org/index.php), [bash], [Linux], [HTML], [JavaScript], [CSS], and [Omnigraffle](https://www.omnigroup.com/omnigraffle) for data modeling and workflow designs.", + }, + { + role: "Lead Software Developer ", + employer: "BuildingBlocks LLC ", + start: "1996-06-01", + end: "1998-02-01", + "z-index": "1", + "css name": "darkcyan", + "css RGB": "#008b8b", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 As lead software developer, built a CD-ROM-based home design application for selecting premium home design products for previewing in the context of images of any household rooms. \n\u2022 Built the prototype using Adobe Photoshop and [Macromedia Director](https://macromedia.fandom.com/wiki/Macromedia_Director).\n\u2022 Built the actual application using using [bash], [Linux], [Java] and [Marimba Bongo](https://www.thriftbooks.com/w/official-marimba-guide-to-bongo_danny-goodman/2574616/#edition=58026223&idiq=42367912) widget layout tool.\n\u2022 Updates for the self-updating application were delivered over the internet using [Marimba Castanet](https://www.infoworld.com/article/2076707/marimba-launches-new-castanet-with-a-less-java-centric-focus.html) push-technology.", + }, + { + role: "Ph.D. Media Arts & Science", + employer: "MIT Media Lab", + start: "1990-09-01", + end: "1997-04-01", + "z-index": "2", + "css name": "blue", + "css RGB": "#0000ff", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022\tDoctor of Philosopy degree, [Massachusetts Institute of Technology]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/MIT-logo.png}, Cambridge, Massachusettes\n\u2022\tMedia Laboratory, Media Arts and Sciences\n\u2022\tTook courses in machine vision, signals and systems, digital signal processing, and stochastics.\n\u2022\tHelped build the operating system for the [Cheops multi-processor system](http://alumni.media.mit.edu/~wad/cheops_CSVT/cheops.html) used for digital video research and for holographic video\n\u2022\t[\u201cVision-assisted modeling for model-based video representations\u201d](https://dspace.mit.edu/handle/1721.1/29123), (Ph.D. Dissertation) MIT, Program in Media Arts & Sciences, 1997\n\u2022\t[\u201cSemiautomatic 3-D Model Extraction from Uncalibrated 2-D Camera Views.\u201d](https://www.media.mit.edu/publications/semiautomatic-3-d-model-extraction-from-uncalibrated-2-d-camera-views-2/) S. Becker & V. M. Bove, Jr., Proc. SPIE Image Synthesis, 2410, 1995, pp. 447-461.\n\u2022\t\u201cSemiautomatic Scene Modeling From 2-D Views with Partially Known Structure.\u201d Shawn Becker, MIT Media Lab Reports, 1995\n\u2022\t\u201cSemiautomatic Camera Lens Calibration from Partially Known Structure\u201d, Shawn Becker, MIT Media Lab Reports, 1994\n\u2022\t[\u201cFormulating a scene probability equation to differentiate the effects of shape & albedo on image brightness.\u201d](https://www.researchgate.net/publication/2668457_Formulating_a_Scene_Probability_Equation_to_Differentiate_the_Effects_of_Shape_and_Albedo_on_Image_Brightness) Shawn Becker, MIT Media Lab Reports, 1994\n\u2022\t\u201cComputation of some projective-chirplet-transform & metaplectic-chirplet-transform subspaces, with applications in image processing.\u201d Steve Mann & Shawn Becker, DSP World Symposium, Boston, Massachusetts, November 1992.\n\u2022 [C programming language], [TclTk], [X11], [HTML], [JavaScript],[CSS],[XMotif], [bash], [Linux]", + }, + { + role: "MS Computer Science", + employer: "BYU", + start: "1987-09-01", + end: "1990-09-01", + "z-index": "2", + "css name": "mediumblue", + "css RGB": "#0000cd", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 Masters of Science degree, [Brigham Young University]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-entrance-150x150.jpg}, Provo, Utah\nTook all courses required for both bachelors and masters degrees in Computer Science\n\u2022 Thesis project [\u201cInteractive Measurement of Three-Dimensional Objects Using a Depth Buffer & Linear Probe.\u201d](https://dl.acm.org/doi/pdf/10.1145/108360.108446) CS MS Thesis, Shawn Becker, William A. Barrett & Dan R. Olsen, ACM Transactions on Graphics, Vol. 10, No. 2, April 1991\n\u2022 Top Research Presentation \u2013 New Tech Research Conference - Brigham Young University \u2013 Provo, UT \u2013 March 1990\n\u2022 [\u201cFast Automated Object Detection Using Signature Parsing.\u201d](https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1192/1/Fast-Automated-Object-Detection-Using-Signature-Parsing/10.1117/12.969720.short) Tim Heaton; Shawn Becker; Kelley Anderson; William Barrett: Proceedings Volume 1192, Intelligent Robots & Computer Vision VIII: Algorithms & Techniques; (1990) https://doi.org/10.1117/12.969720\n\u2022 [\u201cProbabilistic Segmentation of Myocardial Tissue by Deterministic Relaxation.\u201d](https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1737&context=facpub) Jerome A. Broekhuijsen, Shawn C. Becker, & William A. Barrett: IEEE Proceedings of Computers in Cardiology, pp. 99-12, Jerusalem, September 1989.\n\u2022 [\u201cInteractive Measurement of three-Dimensional Cardiac Morphology.\u201d]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/BYU-MS-CS-Skull-Cross-Section-1.jpeg}(https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1736&context=facpub) Shawn C Becker, William A Barrett, October 1989, DOI: 10.1109/CIC.1989.130586, Conference: Computers in Cardiology.\n\u2022 [C programming language], [bash], [Linux], [XMotif], and [X11].", + }, + { + role: "Full Stack Developer", + employer: "Cimmetrix LLC", + start: "1988-06-01", + end: "1989-09-01", + "z-index": "3", + "css name": "blueviolet", + "css RGB": "#8a2be2", + "css color": "", + "text color": "#FFFFFF", + Description: + "\u2022 Front-end software developer of a reverse kinametics path planning system for multi-axis industrial robots for [Cimmetrix]{https://shawn.beckerstudio.com/wp-content/uploads/2023/05/Cimetrix-PDF-combined-logo-150x100.png}.\n\u2022 Technologies used include [bash], [Linux], [C programming language], [bash](https://en.wikipedia.org/wiki/Bourne_shell), [X11] , [Xt toolkit intrinsics](https://en.wikipedia.org/wiki/X_Toolkit_Intrinsics), [Silicon Graphics Irix](https://en.wikipedia.org/wiki/Silicon_Graphics), and [HP-UX](https://en.wikipedia.org/wiki/HP-UX).", + }, + { + role: "Project Manager / Technical Lead ", + employer: "MSC ", + start: "2007-12-01", + end: "2010-08-01", + "z-index": "2", + "css name": "yellow", + "css RGB": "#ffff00", + "css color": "", + "text color": "#000000", + Description: + "\u2022 MSC, now called [OneCall](https://onecallcm.com/), is a leading workers compensation services company. \n\u2022 As project manager and technical lead for this Sierra Vista Group project, I presented fixed schedule-fixed budget project proposals to C-level executives to add features to their legacy call center system used by 10 different healthcare divisions. \n\u2022 Interviewed stakeholders to create functional requirements and technical spefications for each stage of development.\n\u2022 Worked with development team to create work plan, assign tasks.\n\u2022 Oversaw quality assurance and customer approval testing.\n\u2022 Used the MS Office suite of business apps a well as MS Visio. ", + }, + { + role: "Senior Architect ", + employer: "Eleven LLC", + start: "2006-02-01", + end: "2007-12-01", + "z-index": "2", + "css name": "lime", + "css RGB": "#00ff00", + "css color": "", + "text color": "#000000", + Description: + "\u2022 [Eleven LLC](https://www.eleven.net/) built mobile apps used by beverage industry distributors to help manage placement of their products in the shelves and coolers in retail locations. The work done by the Sierra Vista Group was instrumental in their company being acquired by [Trimble Mobile Solutions](https://help.trimblegeospatial.com/TMM/Home.htm). \n\u2022 As the architect and team lead, we used [Java], [bash], [GitHub], [Linix], and [JBoss](https://developers.redhat.com/products/eap/overview) message-oriented middleware platform, [Sybase Anywhere](https://texas.gs.shi.com/Product/30451452/Sybase-SQL-Anywhere-Advanced-Edition) for the client/server based database, and [Windows Mobile](https://en.wikipedia.org/wiki/Windows_Mobile_5.0) running on ruggedized mobile devices. ", + }, + { + role: "Senior Architect", + employer: "Intrusic LLC", + start: "2005-02-01", + end: "2006-02-01", + "z-index": "2", + "css name": "limegreen", + "css RGB": "#32cd32", + "css color": "", + "text color": "#000000", + Description: + "\u2022 [Intrusic LLC](https://www.crunchbase.com/organization/intrusic) built real-time network monitoring systems that identified external and internal network intrusion attempts\n\u2022 As a Sierra Vista Group architech, I helped design and develop an approach for buffering live streaming network traffic for asynchronous package processing. \n\u2022 Used [Debian Linux](https://www.debian.org/), [C programming language](https://www.cprogramming.com/books/ritchie.html), and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software).", + }, + { + role: "Project Manager / Technical Lead ", + employer: "AMI Entertainment ", + start: "2004-02-01", + end: "2005-02-01", + "z-index": "2", + "css name": "olivedrab", + "css RGB": "#6b8e23", + "css color": "", + "text color": "#000000", + Description: + "\u2022 AMI (https://amientertainment.com/) was the internet-music distribution incarnation of Rowe International. \n\u2022 As a Sierra Vista Group project manager and technical lead, I helped design and implement their system for making monthly ACH royalty payments to music copyright owners for mechanical and performance licensing rights.\n\u2022 Used [FileMaker Pro](https://www.claris.com/filemaker/), [bash], [Linux], [HTML], [CSS], [JavaScript], [Java], and [Visio](https://www.microsoft.com/en-us/microsoft-365/visio/flowchart-software).", + }, + { + role: "Project Manager / Technical Lead ", + employer: "Rowe International", + start: "2003-03-01", + end: "2004-02-01", + "z-index": "2", + "css name": "forestgreen", + "css RGB": "#228b22", + "css color": "", + "text color": "#000000", + Description: + "\u2022 [Rowe International](https://pitchbook.com/profiles/company/13178-08) was the leading manufacturer of music jukeboxes. \n\u2022 Sierra Vista Group was consulted to assess their available technologies and create a plan to build their back-end systems to let them become a leading provider of internet-based music.\n\u2022 As project manager and technical lead created the project plan and led the development of a full-stack web application used by jukebox owners and Rowe sales and marketing.\n\u2022 Used [Java], [bash], [Linux], [HTML], [CSS], [JavaScript], [ObjectDesign](https://object.design/), [MySQL](https://www.mysql.com/), and [Adobe Photoshop](https://www.adobe.com/products/photoshop.html). \n", + }, +]; diff --git a/static_content/jobs/jobs.xlsx b/static_content/jobs/jobs.xlsx index 4d8f48928fef25b6813725cf721c3194f27a6303..e2189a06eb9f699f8b01037fd577c15e2530fdb6 100644 GIT binary patch delta 13593 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 diff --git a/static_content/jobs/~$jobs.xlsx b/static_content/jobs/~$jobs.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ea27bc503fd2df13178cf5e3e9a16cf8a18bd75a GIT binary patch literal 165 ycmd-H&PXiJQ*cU6&Q2{-AR6#61T$nXBr=pU