{"id":7635,"date":"2026-01-14T18:35:42","date_gmt":"2026-01-14T17:35:42","guid":{"rendered":"https:\/\/innovacore.group\/?post_type=portfolio&p=7635"},"modified":"2026-03-17T10:42:25","modified_gmt":"2026-03-17T08:42:25","slug":"tamias-pierwszy-pos-dla-spolecznosci-sportowych","status":"publish","type":"portfolio","link":"https:\/\/innovacore.group\/pl\/portfolio\/tamias-pierwszy-pos-dla-spolecznosci-sportowych\/","title":{"rendered":"Tamias &#8211; Pierwszy POS dla spo\u0142eczno\u015bci sportowych"},"content":{"rendered":"\n<p>Tamias is a cutting-edge Point of Sale (POS) solution designed by industry experts to merge seamless retail operations with deep community engagement. Unlike traditional systems, Tamias is uniquely built to interact with sports communities, stadiums, and events. By integrating advanced analytics, loyalty programs, and an intuitive interface, it empowers retailers and clubs to transform simple transactions into lasting fan relationships and sustainable business growth.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pierwszy system POS nap\u0119dzany przez spo\u0142eczno\u015bci sportowe i zaawansowan\u0105 analityk\u0119.<\/p>\n","protected":false},"featured_media":2369,"parent":0,"template":"","meta":{"inline_featured_image":false,"company_name":"Tamias","summary":"Pierwszy POS dla <span class=\"ic-nycd\">Spo\u0142eczno\u015bci sportowe<\/span>","mission":"<p>Aby zrewolucjonizowa\u0107 punkt sprzeda\u017cy, przekszta\u0142caj\u0105c go w punkt kontaktu. Tamias ma na celu wzmocnienie firm \u2014 od lokalnych kawiarni po du\u017ce stadiony \u2014 narz\u0119dziami, kt\u00f3re nie tylko usprawniaj\u0105 operacje, ale tak\u017ce wspieraj\u0105 g\u0142\u0119bokie, oparte na danych zaanga\u017cowanie ich spo\u0142eczno\u015bci i fan\u00f3w.<\/p>\n","impact":"<p>Tamias redefiniuje krajobraz transakcyjny, integruj\u0105c interakcje spo\u0142eczne bezpo\u015brednio w procesie kasowym. Jego zdolno\u015b\u0107 obs\u0142ugi du\u017cych wydarze\u0144 sportowych przy jednoczesnym tworzeniu spersonalizowanych p\u0119tli lojalno\u015bciowych pozwala firmom na monetyzacj\u0119 pasji, czyni\u0105c go kluczowym narz\u0119dziem dla nowoczesnej gospodarki sportowo-handlowej.<\/p>\n","company_logo":"https:\/\/innovacore.group\/wp-content\/uploads\/tamias-logo-innov-innovacore-optimized.jpg","website_url":"https:\/\/tamias.com\/","linkedin_url":"https:\/\/www.linkedin.com\/company\/tamias-pos\/","location":"Norwich, UK","founded_year":"2025","key_numbers":{"item-0":{"metric_label":"+ Sklepy Tymczasowe Zarz\u0105dzane","metric_value":"320"},"item-1":{"metric_label":"Op\u0142aty Miesi\u0119czne","metric_value":"0"},"item-2":{"metric_label":"G\u0142\u00f3wne Turnieje","metric_value":"2"}},"hiring_status":"w ukrytym trybie","sector":"fintech","company_type":"startup","audience":["b2b"],"geo_scope":["globalny"],"business_model":["op\u0142ata transakcyjna"],"funding_stage":"nieujawnione","partnership_type":"inne","logo_animation":"<div id=\"tamias-particle-root\">\r\n    <canvas id=\"tamiasCanvas\"><\/canvas>\r\n<\/div>\r\n\r\n<style>\r\n    #tamias-particle-root {\r\n        width: 100%;\r\n        height: 300px; \/* Hauteur fixe respect\u00e9e *\/\r\n        display: flex;\r\n        justify-content: center;\r\n        align-items: center;\r\n        background: transparent;\r\n        overflow: hidden;\r\n        cursor: crosshair;\r\n    }\r\n<\/style>\r\n\r\n<script>\r\n(function() {\r\n    const canvas = document.getElementById('tamiasCanvas');\r\n    const ctx = canvas.getContext('2d', { willReadFrequently: true });\r\n    const root = document.getElementById('tamias-particle-root');\r\n    \r\n    let width, height;\r\n    let particles = [];\r\n    let mouse = { x: -1000, y: -1000 };\r\n    const particleColor = '#f5f5f5'; \/\/ Gris clair Innovacore\r\n    let time = 0;\r\n\r\n    function init() {\r\n        width = root.offsetWidth;\r\n        height = 300;\r\n        \r\n        const dpr = window.devicePixelRatio || 1;\r\n        canvas.width = width * dpr;\r\n        canvas.height = height * dpr;\r\n        canvas.style.width = width + 'px';\r\n        canvas.style.height = height + 'px';\r\n        ctx.scale(dpr, dpr);\r\n\r\n        createLogoParticles();\r\n    }\r\n\r\n    function createLogoParticles() {\r\n        particles = [];\r\n        const cx = width \/ 2;\r\n        const cy = height \/ 2;\r\n        const isMobile = width < 600;\r\n\r\n        \/\/ --- 1. CONFIGURATION ---\r\n        \/\/ Dimensions relatives\r\n        const iconSize = isMobile ? 50 : 80; \r\n        const fontSize = isMobile ? 50 : 80;\r\n        const gap = 20;\r\n\r\n        \/\/ On va dessiner en blanc pour le scan\r\n        ctx.fillStyle = 'white';\r\n        ctx.strokeStyle = 'white';\r\n        ctx.lineWidth = isMobile ? 4 : 6;\r\n        ctx.lineCap = 'round';\r\n        ctx.lineJoin = 'round';\r\n\r\n        \/\/ Typo arrondie pour \"tamias\"\r\n        ctx.font = `normal ${fontSize}px \"Arial Rounded MT Bold\", \"Varela Round\", \"Quicksand\", Arial, sans-serif`;\r\n        const textMetrics = ctx.measureText('tamias');\r\n        const textWidth = textMetrics.width;\r\n\r\n        \/\/ Calcul du centrage global (Icone + Espace + Texte)\r\n        const totalWidth = iconSize + gap + textWidth;\r\n        const startX = cx - (totalWidth \/ 2);\r\n        const startY = cy;\r\n\r\n        \/\/ --- 2. DESSIN DE L'IC\u00d4NE (L'\u00c9CUREUIL ABSTRAIT) ---\r\n        \/\/ On essaie de reproduire la forme en \"V\" courb\u00e9\r\n        const ix = startX;\r\n        const iy = cy - (iconSize * 0.2); \/\/ Remonter un peu pour aligner avec le texte\r\n\r\n        ctx.beginPath();\r\n        \/\/ Point de d\u00e9part (Haut gauche de la queue)\r\n        ctx.moveTo(ix, iy - iconSize * 0.3); \r\n        \r\n        \/\/ Courbe vers le bas (la pointe du V)\r\n        \/\/ cp1x, cp1y, cp2x, cp2y, x, y\r\n        ctx.bezierCurveTo(\r\n            ix - 5, iy + iconSize * 0.4, \/\/ Control point 1 (bomber vers l'ext\u00e9rieur gauche)\r\n            ix + iconSize * 0.2, iy + iconSize * 0.6, \/\/ Control point 2 (vers le bas)\r\n            ix + iconSize * 0.4, iy + iconSize * 0.6  \/\/ Point bas (Pointe)\r\n        );\r\n\r\n        \/\/ Courbe vers le haut (le dos\/t\u00eate)\r\n        ctx.bezierCurveTo(\r\n            ix + iconSize * 0.6, iy + iconSize * 0.6, \r\n            ix + iconSize * 0.8, iy + iconSize * 0.1, \r\n            ix + iconSize * 0.7, iy - iconSize * 0.1  \/\/ T\u00eate\r\n        );\r\n\r\n        \/\/ Petite boucle pour l'oreille\/t\u00eate (retour vers l'int\u00e9rieur)\r\n        ctx.bezierCurveTo(\r\n            ix + iconSize * 0.6, iy - iconSize * 0.2,\r\n            ix + iconSize * 0.5, iy - iconSize * 0.1,\r\n            ix + iconSize * 0.55, iy + iconSize * 0.1\r\n        );\r\n        \r\n        ctx.stroke();\r\n\r\n        \/\/ L'Oeil (Le petit point)\r\n        ctx.beginPath();\r\n        ctx.arc(ix + iconSize * 0.65, iy - iconSize * 0.05, isMobile ? 2 : 4, 0, Math.PI * 2);\r\n        ctx.fill();\r\n\r\n\r\n        \/\/ --- 3. DESSIN DU TEXTE ---\r\n        ctx.textAlign = 'left';\r\n        ctx.textBaseline = 'middle';\r\n        \/\/ On aligne le texte un peu plus bas pour qu'il soit visuellement centr\u00e9 avec l'ic\u00f4ne\r\n        ctx.fillText('tamias', startX + iconSize + gap, cy);\r\n\r\n\r\n        \/\/ --- 4. SCAN DES PIXELS ---\r\n        const density = 4;\r\n        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;\r\n        const dataWidth = canvas.width; \r\n\r\n        for (let y = 0; y < canvas.height; y += density) {\r\n            for (let x = 0; x < canvas.width; x += density) {\r\n                \/\/ Scan pixel opaque\r\n                if (imageData[(y * dataWidth + x) * 4 + 3] > 128) {\r\n                    const dpr = window.devicePixelRatio || 1;\r\n                    particles.push({\r\n                        x: x \/ dpr,\r\n                        y: y \/ dpr,\r\n                        originX: x \/ dpr,\r\n                        originY: y \/ dpr,\r\n                        vx: 0, \r\n                        vy: 0,\r\n                        size: Math.random() * 1.5 + 0.5,\r\n                        force: Math.random() \r\n                    });\r\n                }\r\n            }\r\n        }\r\n        \r\n        \/\/ Nettoyage\r\n        ctx.clearRect(0, 0, width, height);\r\n    }\r\n\r\n    function draw() {\r\n        ctx.clearRect(0, 0, width, height);\r\n        time += 0.05;\r\n\r\n        ctx.fillStyle = particleColor;\r\n        \r\n        particles.forEach(p => {\r\n            \/\/ 1. Respiration\r\n            const waveX = Math.sin(time * 0.5 + p.y * 0.05) * 2;\r\n            const waveY = Math.cos(time * 0.3 + p.x * 0.05) * 2;\r\n\r\n            \/\/ 2. Interaction\r\n            const dx = mouse.x - p.x;\r\n            const dy = mouse.y - p.y;\r\n            const dist = Math.sqrt(dx*dx + dy*dy);\r\n            const radius = 80;\r\n\r\n            let repelX = 0;\r\n            let repelY = 0;\r\n\r\n            if (dist < radius) {\r\n                const force = (radius - dist) \/ radius;\r\n                const angle = Math.atan2(dy, dx);\r\n                repelX = -Math.cos(angle) * force * 20;\r\n                repelY = -Math.sin(angle) * force * 20;\r\n            }\r\n\r\n            \/\/ 3. Physique\r\n            const targetX = p.originX + waveX;\r\n            const targetY = p.originY + waveY;\r\n\r\n            const ax = (targetX - p.x) * 0.08;\r\n            const ay = (targetY - p.y) * 0.08;\r\n\r\n            p.vx += ax;\r\n            p.vy += ay;\r\n            p.vx += repelX * 0.5;\r\n            p.vy += repelY * 0.5;\r\n            p.vx *= 0.85; \r\n\r\n            p.x += p.vx;\r\n            p.y += p.vy;\r\n\r\n            ctx.beginPath();\r\n            ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);\r\n            ctx.fill();\r\n        });\r\n\r\n        requestAnimationFrame(draw);\r\n    }\r\n\r\n    const updateMouse = (e) => {\r\n        const r = canvas.getBoundingClientRect();\r\n        const cx = e.touches ? e.touches[0].clientX : e.clientX;\r\n        const cy = e.touches ? e.touches[0].clientY : e.clientY;\r\n        mouse.x = cx - r.left;\r\n        mouse.y = cy - r.top;\r\n    };\r\n\r\n    window.addEventListener('resize', init);\r\n    canvas.addEventListener('mousemove', updateMouse);\r\n    canvas.addEventListener('touchmove', updateMouse, {passive: true});\r\n    canvas.addEventListener('mouseleave', () => { mouse.x = -1000; mouse.y = -1000; });\r\n    canvas.addEventListener('touchend', () => { mouse.x = -1000; mouse.y = -1000; });\r\n\r\n    setTimeout(init, 50);\r\n    draw();\r\n})();\r\n<\/script>"},"pt":[],"pipeline":[],"class_list":["post-7635","portfolio","type-portfolio","status-publish","has-post-thumbnail","hentry"],"_links":{"self":[{"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/portfolio\/7635","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/portfolio"}],"about":[{"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/types\/portfolio"}],"version-history":[{"count":1,"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/portfolio\/7635\/revisions"}],"predecessor-version":[{"id":7636,"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/portfolio\/7635\/revisions\/7636"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/media\/2369"}],"wp:attachment":[{"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/media?parent=7635"}],"wp:term":[{"taxonomy":"pt","embeddable":true,"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/pt?post=7635"},{"taxonomy":"pipeline","embeddable":true,"href":"https:\/\/innovacore.group\/pl\/wp-json\/wp\/v2\/pipeline?post=7635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}