{"id":4082,"date":"2020-09-29T11:24:22","date_gmt":"2020-09-29T10:24:22","guid":{"rendered":"https:\/\/solidt.eu\/site\/?p=4082"},"modified":"2020-09-29T12:13:33","modified_gmt":"2020-09-29T11:13:33","slug":"ufi-unique-formula-identifier","status":"publish","type":"post","link":"https:\/\/solidt.eu\/site\/ufi-unique-formula-identifier\/","title":{"rendered":"UFI (Unique Formula Identifier)"},"content":{"rendered":"\n<p>Base source: <a href=\"https:\/\/github.com\/PetrPodrazil\/UFI\">https:\/\/github.com\/PetrPodrazil\/UFI<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/poisoncentres.echa.europa.eu\/documents\/22284544\/22295820\/ufi_developers_manual_en.pdf\/9d47a5c9-ba58-4b5c-8101-7d5610928035\">https:\/\/poisoncentres.echa.europa.eu\/documents\/22284544\/22295820\/ufi_developers_manual_en.pdf\/9d47a5c9-ba58-4b5c-8101-7d5610928035<\/a><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Collections;\nusing System.Linq;\nusing System.Numerics;\nusing System.Text;\nusing System.Text.RegularExpressions;\n\n\npublic class UFI\n{\n\tpublic const string b31chars = \"0123456789ACDEFGHJKMNPQRSTUVWXY\";\n\tprivate static int CalculateChecksum(string ufi)\n\t{\n\t\tif (ufi.Length > 15) ufi = ufi.Substring(1);\n\t\tvar weightedSum = 0;\n\t\tfor (int i = 0; i &lt; 15; i++) weightedSum += (i + 2) * b31chars.IndexOf(ufi[i]);\n\t\treturn (31 - weightedSum % 31) % 31;\n\t}\n\n\tpublic static bool IsUfiValid(string ufi)\n\t{\n\t\tufi = Regex.Replace(ufi?.Trim(), \"\\\\-\", \"\"); \/\/ remove dashes\n\t\tif (ufi.Length != 16) return false; \/\/ check length\n\t\tif (!ufi.All(c => b31chars.Contains(c))) return false;  \/\/ check characters\n\t\tvar checksum = b31chars.IndexOf(ufi[0]); \/\/ checksum (value\/index of first character)\n\t\tvar calculatedChecksum = CalculateChecksum(ufi); \/\/ calculate checksum\n\t\treturn checksum == calculatedChecksum;\n\t}\n\n\tpublic static string GenerateUFI(string VAT, int formulation)\n\t{\n\t\tif (VAT.Length == 0) return \"\";\n\n\t\t\/\/2.1.1 Step 1 \u2013 UFI payload numerical value\n\t\tstring countryCodeIso3166 = GetCountryCodeISO3166(VAT);\n\t\tlong vatLong = VatToNumber(VAT, countryCodeIso3166);\n\t\tBitArray group = GetCountryGroup(countryCodeIso3166);\n\t\tBitArray country = GetCountryCode(countryCodeIso3166);\n\t\tBitArray vatn = VatNumberBits(vatLong, countryCodeIso3166);\n\t\tBitArray formulationN = formulation.ToBinary(28);\n\t\tBitArray togetherStep1 = 0.ToBinary(1).Append(vatn).Append(country).Append(group).Append(formulationN);\n\n\t\t\/\/2.1.2 Step 2 \u2013 UFI payload in base-31\n\t\tstring decimalPayloadString = BinToDec(togetherStep1.ToDigitString());\n\t\tBigInteger payload = BigInteger.Parse(decimalPayloadString);\n\t\tstring base31PayloadStep2 = BigIntegerToStringBaseX(payload, b31chars).PadLeft(15, '0');\n\n\t\t\/\/2.1.3 Step 3 \u2013 Character reorganisation\n\t\tstring reorganisedStep3 = CharacterReorganisation(base31PayloadStep2);\n\t\t\/\/2.1.4 Step 4 \u2013 Checksum calculation\n\t\tint checkSum = CalculateChecksum(reorganisedStep3);\n\n\t\t\/\/ checksum ervoor\n\t\tstring UFIPlainStep4 = $\"{b31chars[checkSum]}{reorganisedStep3}\";\n\t\t\/\/ streepjes ertussen\n\t\treturn Regex.Replace(UFIPlainStep4, @\"^(....)(....)(....)(....)$\", \"$1-$2-$3-$4\");\n\t}\n\n\tpublic static void ReverseUFI(string ufi)\n\t{\n\t\tif (!IsUfiValid(ufi)) throw new Exception(\"UFI code is invalid\");\n\n\t\t\/\/ remove dashes\n\t\tufi = Regex.Replace(ufi?.Trim(), \"\\\\-\", \"\"); \n\t\t\/\/ remove first character\n\t\tufi = ufi.Substring(1);\n\t\t\/\/ backwards character reorganisation\n\t\tvar reversed = ReverseCharacterReorganisation(ufi);\n\t\t\/\/ unbase 31\n\t\tvar bigInt = StringBaseXToBigInteger(reversed, b31chars);\n\t\t\/\/ convert to base2, pad to 74 characters\n\t\tvar binary = ToNBase(bigInt, 2).PadLeft(74, '0');\n\t\t\/\/ split binary parts\n\t\tvar parts = SplitSizes(binary, 28, 4, 7, 34, 1);\n\t\t\/\/ convert binary to decimal\n\t\tvar formulationN = BinaryToDecimal(parts[0]);\n\t\tvar countryGroup = BinaryToDecimal(parts[1]);\n\t\tvar country = BinaryToDecimal(parts[2]);\n\t\tvar vatnr = BinaryToDecimal(parts[3]);\n\n\t\tConsole.WriteLine($\"{countryGroup}; {country}; {vatnr}; {formulationN}\");\n\t}\n\n\tpublic static string[] SplitSizes(string str, params int[] sizes)\n\t{\n\t\tvar length = sizes.Length;\n\t\tvar parts = new string[length];\n\t\tvar start = 0;\n\t\tfor (int i = 0; i &lt; length; i++)\n\t\t{\n\t\t\tparts[i] = str.Substring(start, sizes[i]);\n\t\t\tstart += sizes[i];\n\t\t}\n\t\treturn parts;\n\t}\n\n\tpublic static BigInteger BinaryToDecimal(string binary) => StringBaseXToBigInteger(binary, \"01\");\n\n\tpublic static string ToNBase(BigInteger a, int n)\n\t{\n\t\tvar sb = new StringBuilder();\n\t\twhile (a > 0)\n\t\t{\n\t\t\tsb.Insert(0, a % n);\n\t\t\ta \/= n;\n\t\t}\n\t\treturn sb.ToString();\n\t}\n\n\t\/\/\/ &lt;summary>\n\t\/\/\/ Table 2-2: Rules for VAT number conversion to numerical value\n\t\/\/\/ &lt;\/summary>\n\t\/\/\/ &lt;param name=\"VAT\">&lt;\/param>\n\t\/\/\/ &lt;returns>&lt;\/returns>\n\tinternal static long VatToNumber(string VAT, string Country)\n\t{\n\t\tswitch (Country)\n\t\t{\n\t\t\tcase \"CY\":\n\t\t\t\treturn VatToNumberCy(VAT);\n\t\t\tcase \"ES\":\n\t\t\t\treturn VatToNumberEs(VAT);\n\t\t\tcase \"FR\":\n\t\t\t\treturn VatToNumberFr(VAT);\n\t\t\tcase \"GB\":\n\t\t\t\treturn VatToNumberGb(VAT);\n\t\t\tcase \"IE\":\n\t\t\t\treturn VatToNumberIe(VAT);\n\t\t\tcase \"IS\":\n\t\t\t\treturn VatToNumberIs(VAT);\n\t\t\tdefault:\n\t\t\t\tstring justNumbers = new string(VAT.Where(char.IsDigit).ToArray());\n\t\t\t\tlong.TryParse(justNumbers, out long n);\n\t\t\t\treturn n;\n\t\t}\n\t}\n\n\tprivate static long VatToNumberCy(string VAT)\n\t{\n\t\tstring decimalPart = VAT.Substring(2, 8);\n\t\tchar letter = VAT.Substring(10, 1)[0];\n\t\tint letterIndex = LetterNumberCyGb(letter);\n\n\t\tlong letterPart = letterIndex * (long)Math.Pow(10, 8);\n\t\treturn letterPart + Convert.ToInt64(decimalPart);\n\t}\n\n\tinternal static long VatToNumberEs(string VAT)\n\t{\n\t\tstring decimalPart = VAT.Substring(3, 7);\n\t\tint c1 = LetterNumberEsFrIs(VAT.Substring(2, 1)[0]);\n\t\tint c2 = LetterNumberEsFrIs(VAT.Substring(10, 1)[0]);\n\n\t\tlong letterPart = (36 * c1 + c2) * (long)Math.Pow(10, 7);\n\t\treturn letterPart + Convert.ToInt64(decimalPart);\n\t}\n\n\tinternal static long VatToNumberFr(string VAT)\n\t{\n\t\t\/\/FRAB123456789\n\t\tstring decimalPart = VAT.Substring(4, 9);\n\t\tint c1 = LetterNumberEsFrIs(VAT.Substring(2, 1)[0]);\n\t\tint c2 = LetterNumberEsFrIs(VAT.Substring(3, 1)[0]);\n\n\t\tlong letterPart = (36 * c1 + c2) * (long)Math.Pow(10, 9);\n\t\treturn letterPart + Convert.ToInt64(decimalPart);\n\t}\n\n\tinternal static long VatToNumberGb(string VAT)\n\t{\n\t\t\/\/GB123456789012 or GBAB123\n\t\tstring justNumbers = new string(VAT.Where(char.IsDigit).ToArray());\n\t\tlong.TryParse(justNumbers, out long n);\n\n\t\tif (VAT.Length == 7)\n\t\t{\n\t\t\tint c1 = LetterNumberCyGb(VAT.Substring(2, 1)[0]);\n\t\t\tint c2 = LetterNumberCyGb(VAT.Substring(3, 1)[0]);\n\t\t\tlong letterPart = (26 * c1 + c2) * (long)Math.Pow(10, 3);\n\t\t\treturn letterPart + n;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn (long)Math.Pow(2, 40) + n;\n\t\t}\n\t}\n\n\tinternal static long VatToNumberIe(string VAT)\n\t{\n\t\tRegex regexA = new Regex(\"[0-9][A-Z*+][0-9]{5}[A-Z]\");\n\t\tMatch matchA = regexA.Match(VAT);\n\n\t\tif (matchA.Success)\n\t\t{\n\t\t\t\/\/\"IE9*54321Y\"\n\t\t\tstring d = VAT.Substring(2, 1) + VAT.Substring(VAT.Length - 6, 5);\n\t\t\tint c1 = LetterNumberIe(VAT.Substring(3, 1)[0]);\n\t\t\tint c2 = LetterNumberIe(VAT.Substring(VAT.Length - 1, 1)[0]);\n\n\t\t\tlong letterPart = (26 * c1 + c2) * (long)Math.Pow(10, 6);\n\t\t\treturn letterPart + Convert.ToInt64(d);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t\/\/IE9876543Z\n\t\t\tstring justNumbers = new string(VAT.Where(char.IsDigit).ToArray());\n\t\t\tlong.TryParse(justNumbers, out long N);\n\t\t\tint c1 = LetterNumberCyGb(VAT.Substring(9, 1)[0]);\n\t\t\tint c2 = 0;\n\t\t\tif (VAT.Length == 11)\n\t\t\t\tc2 = LetterNumberCyGb(VAT.Substring(10, 1)[0]);\n\n\t\t\treturn ((long)Math.Pow(2, 33) + ((26 * c2 + c1) * (long)Math.Pow(10, 7) + Convert.ToInt64(N)));\n\t\t}\n\t}\n\n\tinternal static long VatToNumberIs(string VAT)\n\t{\n\t\t\/\/ISAB3D5F\n\t\tlong VN = 0;\n\t\tchar l1 = VAT.Substring(7, 1)[0];\n\t\tchar l2 = VAT.Substring(6, 1)[0];\n\t\tchar l3 = VAT.Substring(5, 1)[0];\n\t\tchar l4 = VAT.Substring(4, 1)[0];\n\t\tchar l5 = VAT.Substring(3, 1)[0];\n\t\tchar l6 = VAT.Substring(2, 1)[0];\n\n\t\tVN += 36 * 36 * 36 * 36 * 36 * LetterNumberEsFrIs(l6);\n\t\tVN += 36 * 36 * 36 * 36 * LetterNumberEsFrIs(l5);\n\t\tVN += 36 * 36 *36  * LetterNumberEsFrIs(l4);\n\t\tVN += 36 * 36 * LetterNumberEsFrIs(l3);\n\t\tVN += 36 * LetterNumberEsFrIs(l2);\n\t\tVN += LetterNumberEsFrIs(l1);\n\t\treturn VN;\n\t}\n\n\tprivate static int LetterNumberIe(char c)\n\t{\n\t\tif (c == '+') return 26;\n\t\tif (c == '*') return 27;\n\t\treturn char.ToUpper(c) - 65;\n\t}\n\n\tprivate static int LetterNumberCyGb(char c)\n\t{\n\t\treturn char.ToUpper(c) - 65;\n\t}\n\n\tinternal static int LetterNumberEsFrIs(char c)\n\t{\n\t\tif (char.IsDigit(c)) return (int)char.GetNumericValue(c);\n\t\treturn char.ToUpper(c) - 55;\n\t}\n\n\tstatic BitArray VatNumberBits(long VAT, string countryCode)\n\t{\n\t\treturn VAT.ToBinary(41 - GetBitsCount(countryCode));\n\t}\n\n\tprivate static readonly int[] mapping = new int[] { 5, 4, 3, 7, 2, 8, 9, 10, 1, 0, 11, 6, 12, 13, 14 };\n\tprivate static readonly int[] reverseMapping = new int[] { 9, 8, 4, 2, 1, 0, 11, 3, 5, 6, 7, 10, 12, 13, 14 };\n\n\tprivate static string CharacterReorganisation(string b31)\n\t{\n\t\tvar sb = new StringBuilder();\n\t\tfor (int i = 0; i &lt; 15; i++)\n\t\t\tsb.Append(b31[mapping[i]]);\n\t\treturn sb.ToString();\n\t}\n\n\tprivate static string ReverseCharacterReorganisation(string b31)\n\t{\n\t\tvar sb = new StringBuilder();\n\t\tfor (int i = 0; i &lt; 15; i++)\n\t\t\tsb.Append(b31[reverseMapping[i]]);\n\t\treturn sb.ToString();\n\t}\n\n\t\/\/\/ &lt;summary>\n\t\/\/\/ Binary string to decimal string\n\t\/\/\/ 0101 => 5\n\t\/\/\/ &lt;\/summary>\n\tprivate static string BinToDec(string value)\n\t{\n\t\tBigInteger res = 0;\n\t\tforeach (char c in value)\n\t\t{\n\t\t\tres &lt;&lt;= 1;\n\t\t\tres += c == '1' ? 1 : 0;\n\t\t}\n\t\treturn res.ToString();\n\t}\n\n\t\/\/\/ &lt;summary>\n\t\/\/\/ BigInteger to any base string\n\t\/\/\/ &lt;\/summary>\n\tprivate static string BigIntegerToStringBaseX(BigInteger value, string baseChars)\n\t{\n\t\tstring result = string.Empty;\n\t\tint targetBase = baseChars.Length;\n\t\tdo\n\t\t{\n\t\t\tresult = baseChars[(int)(value % targetBase)] + result;\n\t\t\tvalue \/= targetBase;\n\t\t}\n\t\twhile (value > 0);\n\t\treturn result;\n\t}\n\n\tprivate static BigInteger StringBaseXToBigInteger(string ufi, string baseChars)\n\t{\n\t\tBigInteger value = 0;\n\t\tvar currentBase = baseChars.Length;\n\t\tvar reversed = ufi.Reverse().ToList();\n\t\tfor (int i = 0; i &lt; reversed.Count; i++)\n\t\t{\n\t\t\tvar baseValue = baseChars.IndexOf(reversed[i]);\n\t\t\tvar digitValue = BigInteger.Pow(new BigInteger(currentBase), i);\n\t\t\tvalue += digitValue * baseValue;\n\t\t}\n\t\treturn value;\n\t}\n\n\tprivate static BitArray GetCountryGroup(string countryCode)\n\t{\n\t\tswitch (countryCode)\n\t\t{\n\t\t\tcase \"\":\n\t\t\t\treturn 0.ToBinary(4);\n\t\t\tcase \"FR\":\n\t\t\t\treturn 1.ToBinary(4);\n\t\t\tcase \"GB\":\n\t\t\t\treturn 2.ToBinary(4);\n\t\t\tcase \"LT\":\n\t\t\tcase \"SE\":\n\t\t\t\treturn 3.ToBinary(4);\n\t\t\tcase \"HR\":\n\t\t\tcase \"IT\":\n\t\t\tcase \"LV\":\n\t\t\tcase \"NL\":\n\t\t\t\treturn 4.ToBinary(4);\n\t\t\tdefault:\n\t\t\t\treturn 5.ToBinary(4);\n\t\t}\n\t}\n\n\tprivate static int GetBitsCount(string countryCode)\n\t{\n\t\tswitch (countryCode)\n\t\t{\n\t\t\tcase \"\":\n\t\t\tcase \"FR\":\n\t\t\tcase \"GB\":\n\t\t\t\treturn 0;\n\t\t\tcase \"LT\":\n\t\t\tcase \"SE\":\n\t\t\t\treturn 1;\n\t\t\tcase \"HR\":\n\t\t\tcase \"IT\":\n\t\t\tcase \"LV\":\n\t\t\tcase \"NL\":\n\t\t\t\treturn 4;\n\t\t\tdefault:\n\t\t\t\treturn 7;\n\t\t}\n\t}\n\n\tprivate static BitArray GetCountryCode(string countryCode)\n\t{\n\t\tswitch (countryCode)\n\t\t{\n\t\t\tdefault:\n\t\t\tcase \"\":\n\t\t\tcase \"FR\":\n\t\t\tcase \"GB\":\n\t\t\t\treturn new BitArray(0);\n\t\t\tcase \"LT\":\n\t\t\t\treturn 0.ToBinary(1);\n\t\t\tcase \"SE\":\n\t\t\t\treturn 1.ToBinary(1);\n\t\t\tcase \"HR\":\n\t\t\t\treturn 0.ToBinary(4);\n\t\t\tcase \"IT\":\n\t\t\t\treturn 1.ToBinary(4);\n\t\t\tcase \"LV\":\n\t\t\t\treturn 2.ToBinary(4);\n\t\t\tcase \"NL\":\n\t\t\t\treturn 3.ToBinary(4);\n\t\t\tcase \"BG\":\n\t\t\t\treturn 0.ToBinary(7);\n\t\t\tcase \"CZ\":\n\t\t\t\treturn 1.ToBinary(7);\n\t\t\tcase \"IE\":\n\t\t\t\treturn 2.ToBinary(7);\n\t\t\tcase \"ES\":\n\t\t\t\treturn 3.ToBinary(7);\n\t\t\tcase \"PL\":\n\t\t\t\treturn 4.ToBinary(7);\n\t\t\tcase \"RO\":\n\t\t\t\treturn 5.ToBinary(7);\n\t\t\tcase \"SK\":\n\t\t\t\treturn 6.ToBinary(7);\n\t\t\tcase \"CY\":\n\t\t\t\treturn 7.ToBinary(7);\n\t\t\tcase \"IS\":\n\t\t\t\treturn 8.ToBinary(7);\n\t\t\tcase \"BE\":\n\t\t\t\treturn 9.ToBinary(7);\n\t\t\tcase \"DE\":\n\t\t\t\treturn 10.ToBinary(7);\n\t\t\tcase \"EE\":\n\t\t\t\treturn 11.ToBinary(7);\n\t\t\tcase \"GR\":\n\t\t\t\treturn 12.ToBinary(7);\n\t\t\tcase \"NO\":\n\t\t\t\treturn 13.ToBinary(7);\n\t\t\tcase \"PT\":\n\t\t\t\treturn 14.ToBinary(7);\n\t\t\tcase \"AT\":\n\t\t\t\treturn 15.ToBinary(7);\n\t\t\tcase \"DK\":\n\t\t\t\treturn 16.ToBinary(7);\n\t\t\tcase \"FI\":\n\t\t\t\treturn 17.ToBinary(7);\n\t\t\tcase \"HU\":\n\t\t\t\treturn 18.ToBinary(7);\n\t\t\tcase \"LU\":\n\t\t\t\treturn 19.ToBinary(7);\n\t\t\tcase \"MT\":\n\t\t\t\treturn 20.ToBinary(7);\n\t\t\tcase \"SI\":\n\t\t\t\treturn 21.ToBinary(7);\n\t\t\tcase \"LI\":\n\t\t\t\treturn 22.ToBinary(7);\n\t\t}\n\t}\n\n\t\/\/\/ &lt;summary>\n\t\/\/\/ Uppercase ISO-3166-1 alpha-2 country codes from VAT\n\t\/\/\/ &lt;\/summary>\n\t\/\/\/ &lt;param name=\"VAT\">&lt;\/param>\n\t\/\/\/ &lt;returns>&lt;\/returns>\n\tprivate static string GetCountryCodeISO3166(string VAT)\n\t{\n\t\tif (VAT.Length == 0) return \"\";\n\t\tif (char.IsDigit(VAT[0])) return \"\";\n\n\t\tstring code = VAT.Substring(0, 2).ToUpper();\n\t\tif (code == \"EL\") code = \"GR\";\n\t\treturn code;\n\t}\n}\n\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public static class Extensions\n{\n\tpublic static string ToDigitString(this BitArray array)\n\t{\n\t\tStringBuilder builder = new StringBuilder();\n\t\tforeach (bool bit in array.Cast&lt;bool>())\n\t\t\tbuilder.Append(bit ? \"1\" : \"0\");\n\n\t\treturn Reverse(builder.ToString());\n\t}\n\n\tprivate static string Reverse(string s)\n\t{\n\t\tchar[] charArray = s.ToCharArray();\n\t\tArray.Reverse(charArray);\n\t\treturn new string(charArray);\n\t}\n\n\tpublic static BitArray Append(this BitArray current, BitArray after)\n\t{\n\t\tbool[] bools = new bool[current.Count + after.Count];\n\t\tcurrent.CopyTo(bools, 0);\n\t\tafter.CopyTo(bools, current.Count);\n\t\treturn new BitArray(bools);\n\t}\n\n\tpublic static BitArray ToBinary(this int numeral, int bitCount)\n\t{\n\t\tBitArray binary = new BitArray(new[] { numeral }) { Length = bitCount };\n\t\treturn binary;\n\t}\n\n\tpublic static BitArray ToBinary(this long numeral, int bitCount)\n\t{\n\t\tBitArray binary = new BitArray(BitConverter.GetBytes(numeral)) { Length = bitCount };\n\t\treturn binary;\n\t}\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Base source: https:\/\/github.com\/PetrPodrazil\/UFI https:\/\/poisoncentres.echa.europa.eu\/documents\/22284544\/22295820\/ufi_developers_manual_en.pdf\/9d47a5c9-ba58-4b5c-8101-7d5610928035<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4082","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/4082","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/comments?post=4082"}],"version-history":[{"count":4,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/4082\/revisions"}],"predecessor-version":[{"id":4087,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/4082\/revisions\/4087"}],"wp:attachment":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/media?parent=4082"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/categories?post=4082"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/tags?post=4082"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}