{"id":38525,"date":"2026-04-21T15:40:41","date_gmt":"2026-04-21T08:40:41","guid":{"rendered":"https:\/\/dps.media\/?page_id=38525"},"modified":"2026-04-21T16:04:26","modified_gmt":"2026-04-21T09:04:26","slug":"tinh-thoi-gian-hoan-von-du-hoc-nghe-duc","status":"publish","type":"page","link":"https:\/\/dps.media\/en\/tinh-thoi-gian-hoan-von-du-hoc-nghe-duc\/","title":{"rendered":"Calculate payback period for vocational study in Germany"},"content":{"rendered":"<div id=\"pdt-repay-tool\">\n  <style>\n    #pdt-repay-tool {\n      --bg: #f6f8fc;\n      --panel: #ffffff;\n      --panel-2: #f8fbff;\n      --text: #102033;\n      --muted: #6a7788;\n      --line: #dbe4f0;\n      --blue: #2563eb;\n      --blue-2: #1d4ed8;\n      --green: #059669;\n      --green-bg: #ecfdf5;\n      --shadow: 0 18px 50px rgba(15, 23, 42, 0.08);\n      --radius: 22px;\n      font-family: inherit;\n      color: var(--text);\n      box-sizing: border-box;\n      width: 100%;\n    }\n    #pdt-repay-tool,\n    #pdt-repay-tool * {\n      box-sizing: border-box;\n      font-family: inherit;\n    }\n    #pdt-repay-tool .pdt-wrap {\n      width: 100%;\n      max-width: 1200px;\n      margin: 0 auto;\n      background:\n        radial-gradient(circle at top left, rgba(37, 99, 235, 0.12), transparent 32%),\n        radial-gradient(circle at top right, rgba(5, 150, 105, 0.10), transparent 28%),\n        var(--bg);\n      border: 1px solid rgba(148, 163, 184, 0.22);\n      border-radius: calc(var(--radius) + 2px);\n      box-shadow: var(--shadow);\n      overflow: hidden;\n    }\n    #pdt-repay-tool .pdt-inner {\n      padding: 22px;\n    }\n    #pdt-repay-tool .pdt-header {\n      display: flex;\n      align-items: flex-start;\n      justify-content: space-between;\n      gap: 18px;\n      padding: 4px 0 18px;\n      border-bottom: 1px solid var(--line);\n      margin-bottom: 18px;\n    }\n    #pdt-repay-tool .pdt-brand {\n      display: flex;\n      gap: 14px;\n      align-items: center;\n    }\n    #pdt-repay-tool .pdt-logo {\n      width: 48px;\n      height: 48px;\n      border-radius: 14px;\n      background: linear-gradient(135deg, var(--blue), var(--blue-2));\n      color: white;\n      display: grid;\n      place-items: center;\n      font-weight: 800;\n      letter-spacing: 0.06em;\n      box-shadow: 0 10px 24px rgba(37, 99, 235, 0.24);\n      flex: 0 0 auto;\n    }\n    #pdt-repay-tool .pdt-title {\n      margin: 0;\n      font-size: clamp(20px, 2vw, 28px);\n      line-height: 1.15;\n      letter-spacing: -0.03em;\n      font-weight: 900;\n    }\n    #pdt-repay-tool .pdt-subtitle {\n      margin: 6px 0 0;\n      color: var(--muted);\n      font-size: 13px;\n      line-height: 1.6;\n    }\n    #pdt-repay-tool .pdt-grid {\n      display: grid;\n      grid-template-columns: 1.05fr 0.95fr;\n      gap: 18px;\n    }\n    #pdt-repay-tool .pdt-panel {\n      background: var(--panel);\n      border: 1px solid var(--line);\n      border-radius: var(--radius);\n      padding: 18px;\n    }\n    #pdt-repay-tool .pdt-section-title {\n      margin: 0 0 14px;\n      font-size: 14px;\n      font-weight: 800;\n      letter-spacing: 0.04em;\n      text-transform: uppercase;\n      color: #334155;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n    #pdt-repay-tool .pdt-section-title .dot {\n      width: 9px;\n      height: 9px;\n      border-radius: 999px;\n      background: var(--blue);\n      box-shadow: 0 0 0 5px rgba(37, 99, 235, 0.10);\n      flex: 0 0 auto;\n    }\n    #pdt-repay-tool .pdt-group {\n      display: grid;\n      gap: 12px;\n    }\n    #pdt-repay-tool .pdt-field {\n      background: var(--panel-2);\n      border: 1px solid rgba(148, 163, 184, 0.22);\n      border-radius: 16px;\n      padding: 12px 12px 10px;\n    }\n    #pdt-repay-tool .pdt-field-head {\n      display: flex;\n      align-items: baseline;\n      justify-content: space-between;\n      gap: 12px;\n      margin-bottom: 9px;\n    }\n    #pdt-repay-tool .pdt-label {\n      font-size: 12px;\n      font-weight: 800;\n      letter-spacing: 0.03em;\n      text-transform: uppercase;\n      color: #475569;\n    }\n    #pdt-repay-tool .pdt-value {\n      font-size: 13px;\n      font-weight: 700;\n      color: #0f172a;\n      font-variant-numeric: tabular-nums;\n      white-space: nowrap;\n    }\n    #pdt-repay-tool input[type=\"range\"] {\n      width: 100%;\n      margin: 0;\n      accent-color: var(--blue);\n    }\n    #pdt-repay-tool input[type=\"number\"] {\n      width: 100%;\n      border: 1px solid rgba(148, 163, 184, 0.30);\n      border-radius: 12px;\n      padding: 10px 12px;\n      font-size: 14px;\n      line-height: 1.4;\n      color: var(--text);\n      background: white;\n    }\n    #pdt-repay-tool input[type=\"number\"]:focus {\n      outline: none;\n      border-color: rgba(37, 99, 235, 0.65);\n      box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);\n    }\n    #pdt-repay-tool input:focus-visible {\n      outline: 2px solid rgba(37, 99, 235, 0.7);\n      outline-offset: 2px;\n    }\n    #pdt-repay-tool .pdt-summary {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 12px;\n      margin-bottom: 14px;\n    }\n    #pdt-repay-tool .pdt-metric {\n      background: linear-gradient(180deg, #fff, #f8fbff);\n      border: 1px solid var(--line);\n      border-radius: 18px;\n      padding: 14px;\n      min-height: 112px;\n      display: flex;\n      flex-direction: column;\n      justify-content: space-between;\n    }\n    #pdt-repay-tool .pdt-metric .kicker {\n      font-size: 12px;\n      color: var(--muted);\n      font-weight: 800;\n      text-transform: uppercase;\n      letter-spacing: 0.03em;\n    }\n    #pdt-repay-tool .pdt-metric .number {\n      font-size: clamp(20px, 2.2vw, 30px);\n      font-weight: 900;\n      letter-spacing: -0.04em;\n      line-height: 1.05;\n      margin-top: 8px;\n      font-variant-numeric: tabular-nums;\n    }\n    #pdt-repay-tool .pdt-metric .hint {\n      margin-top: 8px;\n      font-size: 12px;\n      color: var(--muted);\n      line-height: 1.55;\n    }\n    #pdt-repay-tool .payback {\n      border-left: 4px solid var(--green);\n    }\n    #pdt-repay-tool .payback .kicker,\n    #pdt-repay-tool .payback .number {\n      color: var(--green);\n    }\n    #pdt-repay-tool .chart-box {\n      background: linear-gradient(180deg, #fff, #f8fbff);\n      border: 1px solid var(--line);\n      border-radius: 18px;\n      padding: 14px;\n    }\n    #pdt-repay-tool .chart-head {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 12px;\n      margin-bottom: 10px;\n    }\n    #pdt-repay-tool .chart-title {\n      margin: 0;\n      font-size: 13px;\n      font-weight: 800;\n      text-transform: uppercase;\n      letter-spacing: 0.04em;\n      color: #334155;\n    }\n    #pdt-repay-tool .legend {\n      display: flex;\n      gap: 12px;\n      flex-wrap: wrap;\n      font-size: 11px;\n      color: var(--muted);\n      font-weight: 700;\n      text-transform: uppercase;\n      letter-spacing: 0.03em;\n    }\n    #pdt-repay-tool .legend span {\n      display: inline-flex;\n      align-items: center;\n      gap: 6px;\n    }\n    #pdt-repay-tool .legend i {\n      width: 10px;\n      height: 10px;\n      border-radius: 999px;\n      display: inline-block;\n    }\n    #pdt-repay-tool .callout {\n      margin-top: 14px;\n      border-radius: 18px;\n      padding: 14px;\n      background: var(--green-bg);\n      border: 1px solid #bbf7d0;\n    }\n    #pdt-repay-tool .callout-title {\n      margin: 0 0 8px;\n      font-size: 14px;\n      color: #064e3b;\n      font-weight: 800;\n    }\n    #pdt-repay-tool .callout-text {\n      margin: 0;\n      color: #0f5132;\n      line-height: 1.65;\n      font-size: 13px;\n    }\n    #pdt-repay-tool .footer {\n      display: flex;\n      justify-content: space-between;\n      gap: 12px;\n      margin-top: 14px;\n      padding-top: 14px;\n      border-top: 1px solid var(--line);\n      color: var(--muted);\n      font-size: 12px;\n      flex-wrap: wrap;\n    }\n    #pdt-repay-tool .mini-grid {\n      display: grid;\n      grid-template-columns: repeat(2, minmax(0, 1fr));\n      gap: 12px;\n      margin-top: 12px;\n    }\n    #pdt-repay-tool .mini-grid .pdt-field {\n      padding: 12px;\n    }\n    #pdt-repay-tool .inline {\n      display: grid;\n      grid-template-columns: 1fr;\n      gap: 10px;\n    }\n    #pdt-repay-tool .currency {\n      font-variant-numeric: tabular-nums;\n    }\n    #pdt-repay-tool .chart-wrap {\n      width: 100%;\n      overflow: hidden;\n      border-radius: 14px;\n      background: #f8fbff;\n      border: 1px solid rgba(148, 163, 184, 0.18);\n    }\n    #pdt-repay-tool svg {\n      display: block;\n      width: 100%;\n      height: auto;\n    }\n    @media (max-width: 960px) {\n      #pdt-repay-tool .pdt-grid,\n      #pdt-repay-tool .pdt-summary,\n      #pdt-repay-tool .mini-grid {\n        grid-template-columns: 1fr;\n      }\n      #pdt-repay-tool .pdt-header {\n        flex-direction: column;\n      }\n    }\n  <\/style>\n\n  <div class=\"pdt-wrap\">\n    <div class=\"pdt-inner\">\n      <div class=\"pdt-header\">\n        <div class=\"pdt-brand\">\n          <div class=\"pdt-logo\" aria-hidden=\"true\">PDT<\/div>\n          <div>\n            <div class=\"pdt-title\">Cost &amp; payback calculator for vocational study in Germany<\/div>\n            <div class=\"pdt-subtitle\">Lightweight version to embed into WordPress. No React needed, no external libraries.<\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"pdt-grid\">\n        <div class=\"pdt-panel\">\n          <div class=\"pdt-section-title\"><span class=\"dot\" aria-hidden=\"true\"><\/span><span>Enter data<\/span><\/div>\n          <div class=\"pdt-group\">\n            <div class=\"pdt-field\">\n              <div class=\"pdt-field-head\"><div class=\"pdt-label\">Learn German &amp; take B1 exam<\/div><div class=\"pdt-value currency\" data-out=\"tuition\"><\/div><\/div>\n              <input data-input=\"tuition\" type=\"range\" min=\"0\" max=\"70000000\" step=\"1000000\">\n            <\/div>\n            <div class=\"pdt-field\">\n              <div class=\"pdt-field-head\"><div class=\"pdt-label\">Application and paperwork fees<\/div><div class=\"pdt-value currency\" data-out=\"dossier\"><\/div><\/div>\n              <input data-input=\"dossier\" type=\"range\" min=\"0\" max=\"50000000\" step=\"1000000\">\n            <\/div>\n            <div class=\"pdt-field\">\n              <div class=\"pdt-field-head\"><div class=\"pdt-label\">Airfare &amp; visa<\/div><div class=\"pdt-value currency\" data-out=\"visa\"><\/div><\/div>\n              <input data-input=\"visa\" type=\"range\" min=\"0\" max=\"40000000\" step=\"1000000\">\n            <\/div>\n            <div class=\"pdt-field\">\n              <div class=\"pdt-field-head\"><div class=\"pdt-label\">Agency service fee<\/div><div class=\"pdt-value currency\" data-out=\"service\"><\/div><\/div>\n              <input data-input=\"service\" type=\"range\" min=\"0\" max=\"150000000\" step=\"1000000\">\n            <\/div>\n            <div class=\"pdt-field\">\n              <div class=\"pdt-field-head\"><div class=\"pdt-label\">Other costs<\/div><div class=\"pdt-value currency\" data-out=\"other\"><\/div><\/div>\n              <input data-input=\"other\" type=\"range\" min=\"0\" max=\"50000000\" step=\"1000000\">\n            <\/div>\n            <div class=\"pdt-field\">\n              <div class=\"pdt-field-head\"><div class=\"pdt-label\">Blocked account<\/div><div class=\"pdt-value\" data-out=\"blocked\"><\/div><\/div>\n              <input data-input=\"blocked\" type=\"range\" min=\"0\" max=\"7000\" step=\"100\">\n            <\/div>\n            <div class=\"mini-grid\">\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Exchange rate 1 EUR = VND<\/div><div class=\"pdt-value currency\" data-out=\"rate\"><\/div><\/div>\n                <input data-input=\"rate\" type=\"number\" min=\"10000\" step=\"100\">\n              <\/div>\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Living expenses\/month<\/div><div class=\"pdt-value currency\" data-out=\"living\"><\/div><\/div>\n                <input data-input=\"living\" type=\"range\" min=\"500\" max=\"1500\" step=\"50\">\n              <\/div>\n            <\/div>\n            <div class=\"mini-grid\">\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Apprenticeship salary year 1\/month<\/div><div class=\"pdt-value currency\" data-out=\"salary1\"><\/div><\/div>\n                <input data-input=\"salary1\" type=\"range\" min=\"800\" max=\"1500\" step=\"50\">\n              <\/div>\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Apprenticeship salary year 2\/month<\/div><div class=\"pdt-value currency\" data-out=\"salary2\"><\/div><\/div>\n                <input data-input=\"salary2\" type=\"range\" min=\"900\" max=\"1600\" step=\"50\">\n              <\/div>\n            <\/div>\n            <div class=\"mini-grid\">\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Apprenticeship salary year 3\/month<\/div><div class=\"pdt-value currency\" data-out=\"salary3\"><\/div><\/div>\n                <input data-input=\"salary3\" type=\"range\" min=\"1000\" max=\"1800\" step=\"50\">\n              <\/div>\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Minijob\/month<\/div><div class=\"pdt-value currency\" data-out=\"minijob\"><\/div><\/div>\n                <input data-input=\"minijob\" type=\"range\" min=\"0\" max=\"538\" step=\"10\">\n              <\/div>\n            <\/div>\n            <div class=\"mini-grid\">\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Net salary after graduation<\/div><div class=\"pdt-value currency\" data-out=\"gradSalary\"><\/div><\/div>\n                <input data-input=\"gradSalary\" type=\"range\" min=\"1500\" max=\"4000\" step=\"100\">\n              <\/div>\n              <div class=\"pdt-field\">\n                <div class=\"pdt-field-head\"><div class=\"pdt-label\">Living expenses after graduation<\/div><div class=\"pdt-value currency\" data-out=\"gradLiving\"><\/div><\/div>\n                <input data-input=\"gradLiving\" type=\"range\" min=\"800\" max=\"2000\" step=\"50\">\n              <\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"pdt-panel\">\n          <div class=\"pdt-section-title\"><span class=\"dot\" aria-hidden=\"true\"><\/span><span>Results<\/span><\/div>\n          <div class=\"pdt-summary\">\n            <div class=\"pdt-metric\">\n              <div class=\"kicker\">Total investment<\/div>\n              <div class=\"number currency\" data-out=\"investment\"><\/div>\n              <div class=\"hint\">Includes initial costs and the converted blocked account.<\/div>\n            <\/div>\n            <div class=\"pdt-metric payback\">\n              <div class=\"kicker\">Payback period<\/div>\n              <div class=\"number\" data-out=\"payback\"><\/div>\n              <div class=\"hint\" data-out=\"paybackNote\"><\/div>\n            <\/div>\n            <div class=\"pdt-metric\">\n              <div class=\"kicker\">Assets after 5 years<\/div>\n              <div class=\"number\" data-out=\"asset\"><\/div>\n              <div class=\"hint\">Accumulated value after 60 months.<\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"chart-box\">\n            <div class=\"chart-head\">\n              <div class=\"chart-title\">5-year cash flow chart<\/div>\n              <div class=\"legend\">\n                <span><i style=\"background:#94a3b8\" aria-hidden=\"true\"><\/i> Cost<\/span>\n                <span><i style=\"background:#2563eb\" aria-hidden=\"true\"><\/i> Accumulation<\/span>\n                <span><i style=\"background:#10b981\" aria-hidden=\"true\"><\/i> Payback<\/span>\n              <\/div>\n            <\/div>\n            <div class=\"chart-wrap\">\n              <svg viewbox=\"0 0 860 340\" role=\"img\" aria-label=\"Cash flow chart\">\n                <defs>\n                  <lineargradient id=\"pdtArea\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n                    <stop offset=\"0%\" stop-color=\"#2563eb\" stop-opacity=\"0.30\"><\/stop>\n                    <stop offset=\"100%\" stop-color=\"#2563eb\" stop-opacity=\"0.02\"><\/stop>\n                  <\/lineargradient>\n                <\/defs>\n                <g data-layer=\"grid\"><\/g>\n                <g data-layer=\"chart\"><\/g>\n                <g data-layer=\"labels\"><\/g>\n              <\/svg>\n            <\/div>\n          <\/div>\n\n          <div class=\"callout\">\n            <div class=\"callout-title\">Financial lesson<\/div>\n            <div class=\"callout-text\" data-out=\"lesson\"><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"footer\">\n        <div>\u00a9 PDT Education<\/div>\n        <div>Data updates based on the figures you enter directly on the page.<\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\n(function () {\n  var root = document.getElementById('pdt-repay-tool');\n  if (!root) {\n    return;\n  }\n\n  var defaults = {\n    tuition: 35000000,\n    dossier: 20000000,\n    visa: 20000000,\n    service: 65000000,\n    other: 10000000,\n    blocked: 0,\n    rate: 27500,\n    salary1: 1000,\n    salary2: 1100,\n    salary3: 1200,\n    minijob: 0,\n    living: 850,\n    gradSalary: 2200,\n    gradLiving: 1100\n  };\n\n  var state = {};\n  var inputs = {};\n  var outputs = {};\n  var outKeys = ['tuition', 'dossier', 'visa', 'service', 'other', 'blocked', 'rate', 'salary1', 'salary2', 'salary3', 'minijob', 'living', 'gradSalary', 'gradLiving', 'investment', 'payback', 'paybackNote', 'asset', 'lesson'];\n\n  function copyDefaults() {\n    var key;\n    for (key in defaults) {\n      if (Object.prototype.hasOwnProperty.call(defaults, key)) {\n        state[key] = defaults[key];\n      }\n    }\n  }\n\n  function formatVND(value) {\n    return new Intl.NumberFormat('vi-VN', {\n      style: 'currency',\n      currency: 'VND',\n      maximumFractionDigits: 0\n    }).format(value);\n  }\n\n  function formatEUR(value) {\n    return new Intl.NumberFormat('de-DE', {\n      style: 'currency',\n      currency: 'EUR',\n      maximumFractionDigits: 0\n    }).format(value);\n  }\n\n  function formatCompactVND(value) {\n    if (Math.floor(Math.abs(value) \/ 1000000000) !== 0) {\n      return (value \/ 1000000000).toFixed(2) + ' T\u1ef7 \u20ab';\n    }\n    if (Math.floor(Math.abs(value) \/ 1000000) !== 0) {\n      return (value \/ 1000000).toFixed(1) + ' Tr \u20ab';\n    }\n    return formatVND(value);\n  }\n\n  function clamp(value, min, max) {\n    return Math.min(max, Math.max(min, value));\n  }\n\n  function setValue(key, value) {\n    state[key] = value;\n    if (inputs[key]) {\n      if (String(inputs[key].value) !== String(value)) {\n        inputs[key].value = value;\n      }\n    }\n  }\n\n  function writeText(node, value) {\n    if (node) {\n      node.textContent = value;\n    }\n  }\n\n  function createSvgEl(tag, attrs, parent) {\n    var el = document.createElementNS('http:\/\/www.w3.org\/2000\/svg', tag);\n    var key;\n    for (key in attrs) {\n      if (Object.prototype.hasOwnProperty.call(attrs, key)) {\n        el.setAttribute(key, String(attrs[key]));\n      }\n    }\n    parent.appendChild(el);\n    return el;\n  }\n\n  function renderChart(series, paybackMonth, initial) {\n    var svg = root.querySelector('svg');\n    var gridLayer = svg.querySelector('[data-layer=\"grid\"]');\n    var chartLayer = svg.querySelector('[data-layer=\"chart\"]');\n    var labelLayer = svg.querySelector('[data-layer=\"labels\"]');\n    var width = 860;\n    var height = 340;\n    var pad = { top: 18, right: 24, bottom: 42, left: 72 };\n    var plotW = width - pad.left - pad.right;\n    var plotH = height - pad.top - pad.bottom;\n    var values = [];\n    var i = 0;\n    var minVal;\n    var maxVal;\n    var yMin;\n    var yMax;\n    var yRange;\n    var xFor;\n    var yFor;\n    var points = [];\n    var area;\n    var yTicks;\n    var year;\n    var yearX;\n    var point;\n    var index;\n    var x;\n    var badge;\n    var txt;\n    var y;\n    var t;\n\n    gridLayer.innerHTML = '';\n    chartLayer.innerHTML = '';\n    labelLayer.innerHTML = '';\n\n    while (i !== series.length) {\n      values.push(series[i].cumulative);\n      i = i + 1;\n    }\n\n    minVal = Math.min.apply(Math, values.concat([-initial]));\n    maxVal = Math.max.apply(Math, values.concat([0]));\n    yMin = Math.min(0, minVal * 1.1);\n    yMax = Math.max(0, maxVal * 1.1);\n    yRange = Math.max(1, yMax - yMin);\n\n    xFor = function (month) {\n      return pad.left + (month \/ 60) * plotW;\n    };\n\n    yFor = function (value) {\n      return pad.top + (1 - (value - yMin) \/ yRange) * plotH;\n    };\n\n    year = 0;\n    while (year !== 6) {\n      yearX = xFor(year * 12);\n      createSvgEl('line', {\n        x1: yearX,\n        y1: pad.top,\n        x2: yearX,\n        y2: height - pad.bottom,\n        stroke: '#e2e8f0',\n        'stroke-dasharray': '4 6'\n      }, gridLayer);\n\n      t = createSvgEl('text', {\n        x: yearX,\n        y: height - 14,\n        'text-anchor': 'middle',\n        fill: '#64748b',\n        'font-size': '12',\n        'font-weight': '700'\n      }, labelLayer);\n      t.textContent = year === 0 ? 'B\u1eaft \u0111\u1ea7u' : 'N\u0103m ' + year;\n      year = year + 1;\n    }\n\n    i = 0;\n    while (i !== 3) {\n      y = pad.top + (0.25 * (i + 1)) * plotH;\n      createSvgEl('line', {\n        x1: pad.left,\n        y1: y,\n        x2: width - pad.right,\n        y2: y,\n        stroke: '#e2e8f0',\n        'stroke-dasharray': '4 6'\n      }, gridLayer);\n      i = i + 1;\n    }\n\n    y = yFor(0);\n    createSvgEl('line', {\n      x1: pad.left,\n      y1: y,\n      x2: width - pad.right,\n      y2: y,\n      stroke: '#94a3b8',\n      'stroke-width': '1.5'\n    }, chartLayer);\n\n    i = 0;\n    while (i !== series.length) {\n      point = series[i];\n      points.push(xFor(point.month).toFixed(2) + ',' + yFor(point.cumulative).toFixed(2));\n      i = i + 1;\n    }\n\n    area = 'M ' + xFor(0) + ' ' + yFor(0) + ' L ' + points.join(' L ') + ' L ' + xFor(60) + ' ' + yFor(0) + ' Z';\n    createSvgEl('path', { d: area, fill: 'url(#pdtArea)' }, chartLayer);\n    createSvgEl('path', {\n      d: 'M ' + points.join(' L '),\n      fill: 'none',\n      stroke: '#2563eb',\n      'stroke-width': '4',\n      'stroke-linecap': 'round',\n      'stroke-linejoin': 'round'\n    }, chartLayer);\n\n    index = 0;\n    while (index !== series.length) {\n      point = series[index];\n      var pointIsPositive = Math.abs(point.cumulative) === point.cumulative;\n      if (index === 0) {\n        createSvgEl('circle', {\n          cx: xFor(point.month),\n          cy: yFor(point.cumulative),\n          r: 4.5,\n          fill: pointIsPositive ? '#10b981' : '#2563eb',\n          stroke: 'white',\n          'stroke-width': '2'\n        }, chartLayer);\n      } else {\n        if (index === series.length - 1) {\n          createSvgEl('circle', {\n            cx: xFor(point.month),\n            cy: yFor(point.cumulative),\n            r: 4.5,\n            fill: pointIsPositive ? '#10b981' : '#2563eb',\n            stroke: 'white',\n            'stroke-width': '2'\n          }, chartLayer);\n        } else {\n          if (index % 6 === 0) {\n            createSvgEl('circle', {\n              cx: xFor(point.month),\n              cy: yFor(point.cumulative),\n              r: 3.2,\n              fill: pointIsPositive ? '#10b981' : '#2563eb',\n              stroke: 'white',\n              'stroke-width': '2'\n            }, chartLayer);\n          }\n        }\n      }\n      index = index + 1;\n    }\n\n    if (paybackMonth !== null) {\n      if (paybackMonth !== 0) {\n        x = xFor(paybackMonth);\n        createSvgEl('line', {\n          x1: x,\n          y1: pad.top,\n          x2: x,\n          y2: height - pad.bottom,\n          stroke: '#10b981',\n          'stroke-dasharray': '5 5',\n          'stroke-width': '2'\n        }, chartLayer);\n        badge = createSvgEl('rect', {\n          x: x - 36,\n          y: pad.top - 8,\n          rx: 10,\n          ry: 10,\n          width: 72,\n          height: 24,\n          fill: '#10b981'\n        }, chartLayer);\n        txt = createSvgEl('text', {\n          x: x,\n          y: pad.top + 9,\n          'text-anchor': 'middle',\n          fill: 'white',\n          'font-size': '11',\n          'font-weight': '800'\n        }, chartLayer);\n        txt.textContent = 'Ho\u00e0n v\u1ed1n';\n      }\n    }\n\n    yTicks = [yMin, (yMin + yMax) \/ 2, yMax];\n    i = 0;\n    while (i !== yTicks.length) {\n      y = yFor(yTicks[i]);\n      t = createSvgEl('text', {\n        x: 12,\n        y: y + 4,\n        fill: '#64748b',\n        'font-size': '12',\n        'font-weight': '700'\n      }, labelLayer);\n      t.textContent = yTicks[i] === 0 ? '0' : formatCompactVND(yTicks[i]).replace(' \u20ab', '');\n      i = i + 1;\n    }\n  }\n\n  function bindInput(key) {\n    var el = root.querySelector('[data-input=\"' + key + '\"]');\n    inputs[key] = el;\n    if (!el) {\n      return;\n    }\n\n    if (el.type === 'range') {\n      el.value = state[key];\n      el.addEventListener('input', function () {\n        setValue(key, Number(el.value));\n        updateOutputs();\n      });\n      return;\n    }\n\n    el.value = state[key];\n    el.addEventListener('input', function () {\n      var minValue = 0;\n      var maxValue = 0;\n      var currentValue = 0;\n      if (el.min !== '') {\n        minValue = Number(el.min);\n      }\n      if (el.max !== '') {\n        maxValue = Number(el.max);\n      }\n      if (el.value !== '') {\n        currentValue = Number(el.value);\n      }\n      var next = clamp(currentValue, minValue, maxValue);\n      setValue(key, next);\n      updateOutputs();\n    });\n    el.addEventListener('blur', function () {\n      el.value = state[key];\n    });\n  }\n\n  function updateOutputs() {\n    var initial = state.tuition + state.dossier + state.visa + state.service + state.other + (state.blocked * state.rate);\n    var saveYear1 = (state.salary1 + state.minijob) - state.living;\n    var saveYear2 = (state.salary2 + state.minijob) - state.living;\n    var saveYear3 = (state.salary3 + state.minijob) - state.living;\n    var savePost = state.gradSalary - state.gradLiving;\n    var cumulative = -initial;\n    var series = [];\n    var paybackMonth = null;\n    var m = 0;\n    var phaseIndex;\n    var savingsEUR;\n    var phase;\n\n    series.push({ month: 0, cumulative: cumulative, phase: '\u0110\u1ea7u t\u01b0' });\n\n    m = 1;\n    while (m !== 61) {\n      phaseIndex = Math.floor((m - 1) \/ 12);\n      savingsEUR = 0;\n      phase = '\u0110i l\u00e0m';\n\n      if (phaseIndex === 0) {\n        savingsEUR = saveYear1;\n        phase = 'N\u0103m 1';\n      } else {\n        if (phaseIndex === 1) {\n          savingsEUR = saveYear2;\n          phase = 'N\u0103m 2';\n        } else {\n          if (phaseIndex === 2) {\n            savingsEUR = saveYear3;\n            phase = 'N\u0103m 3';\n          } else {\n            savingsEUR = savePost;\n          }\n        }\n      }\n\n      cumulative = cumulative + (savingsEUR * state.rate);\n\n      if (paybackMonth === null) {\n        if (Math.abs(cumulative) === cumulative) {\n          paybackMonth = m;\n        }\n      }\n\n      series.push({ month: m, cumulative: cumulative, phase: phase });\n      m = m + 1;\n    }\n\n    writeText(outputs.tuition, formatVND(state.tuition));\n    writeText(outputs.dossier, formatVND(state.dossier));\n    writeText(outputs.visa, formatVND(state.visa));\n    writeText(outputs.service, formatVND(state.service));\n    writeText(outputs.other, formatVND(state.other));\n    writeText(outputs.blocked, Number(state.blocked).toLocaleString('de-DE') + ' EUR');\n    writeText(outputs.rate, Number(state.rate).toLocaleString('vi-VN') + ' \u20ab');\n    writeText(outputs.salary1, formatEUR(state.salary1));\n    writeText(outputs.salary2, formatEUR(state.salary2));\n    writeText(outputs.salary3, formatEUR(state.salary3));\n    writeText(outputs.minijob, formatEUR(state.minijob));\n    writeText(outputs.living, formatEUR(state.living));\n    writeText(outputs.gradSalary, formatEUR(state.gradSalary));\n    writeText(outputs.gradLiving, formatEUR(state.gradLiving));\n    writeText(outputs.investment, formatCompactVND(initial));\n\n    if (paybackMonth !== null) {\n      writeText(outputs.payback, (paybackMonth \/ 12).toFixed(1) + ' n\u0103m');\n      writeText(outputs.paybackNote, '~ Th\u00e1ng ' + paybackMonth);\n    } else {\n      writeText(outputs.payback, 'Ch\u01b0a ho\u00e0n v\u1ed1n');\n      writeText(outputs.paybackNote, 'Tr\u00ean 5 n\u0103m');\n    }\n\n    writeText(outputs.asset, formatCompactVND(cumulative));\n    writeText(outputs.lesson, '\u0110i l\u00e0m th\u00eam kho\u1ea3n 200 - 300 EUR\/th\u00e1ng c\u00f3 th\u1ec3 r\u00fat ng\u1eafn th\u1eddi gian ho\u00e0n v\u1ed1n \u0111\u00e1ng k\u1ec3. \u01afu ti\u00ean v\u1eabn l\u00e0 h\u1ecdc v\u00e0 \u0111\u1ed7 ch\u1ee9ng ch\u1ec9 B2\/C1.');\n\n    renderChart(series, paybackMonth, initial);\n  }\n\n  copyDefaults();\n\n  var i = 0;\n  while (i !== outKeys.length) {\n    outputs[outKeys[i]] = root.querySelector('[data-out=\"' + outKeys[i] + '\"]');\n    i = i + 1;\n  }\n\n  bindInput('tuition');\n  bindInput('dossier');\n  bindInput('visa');\n  bindInput('service');\n  bindInput('other');\n  bindInput('blocked');\n  bindInput('rate');\n  bindInput('salary1');\n  bindInput('salary2');\n  bindInput('salary3');\n  bindInput('minijob');\n  bindInput('living');\n  bindInput('gradSalary');\n  bindInput('gradLiving');\n\n  updateOutputs();\n})();\n<\/script>","protected":false},"excerpt":{"rendered":"<p>PDT C\u00f4ng c\u1ee5 t\u00ednh chi ph\u00ed &#038; ho\u00e0n v\u1ed1n du h\u1ecdc ngh\u1ec1 \u0110\u1ee9c B\u1ea3n g\u1ecdn nh\u1eb9 \u0111\u1ec3 d\u00e1n v\u00e0o WordPress. Kh\u00f4ng c\u1ea7n React, kh\u00f4ng c\u1ea7n th\u01b0 vi\u1ec7n ngo\u00e0i. Nh\u1eadp s\u1ed1 li\u1ec7u H\u1ecdc ti\u1ebfng \u0110\u1ee9c &#038; thi B1 Ph\u00ed h\u1ed3 s\u01a1, gi\u1ea5y t\u1edd V\u00e9 m\u00e1y bay &#038; visa Ph\u00ed d\u1ecbch v\u1ee5 trung t\u00e2m Chi ph\u00ed kh\u00e1c [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-38525","page","type-page","status-publish","hentry"],"acf":[],"rankmath_keywords":{"primary":"","secondary":[""]},"yoast_keywords":{"primary":"","secondary":[]},"yoast_focuskw":"","rankmath_focuskw":"","seo_keywords":{"primary":"","secondary":[""]},"_links":{"self":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/pages\/38525","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/comments?post=38525"}],"version-history":[{"count":5,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/pages\/38525\/revisions"}],"predecessor-version":[{"id":38532,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/pages\/38525\/revisions\/38532"}],"wp:attachment":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/media?parent=38525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}