TaiShang FaaS System

Code Loader

upload ur code by AR token / upload ur code by Matic token


check code on explorer:

https://viewblock.io/arweave/tx/1R7Y8U1bjC0EGePqHDC_0ODY-GiWxOw_rUPQOfXZLGA

defmodule CodesOnChain.NftRender.NType do
  @moduledoc """
    This module is use for render abstract NFT to an rendered NFT.
  """

  alias Components.NFTHandler

  @traits %{
    n: "<text",
    img: "<image"
    }

  @header %{
    origin: "<svg xmlns=\"http://www.w3.org/2000/svg\" preserveAspectRatio=\"xMinYMin meet\" viewBox=\"0 0 350 350\">",
    replace: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" preserveAspectRatio=\"xMinYMin meet\" viewBox=\"0 0 400 400\">"
  }

  @rect "<rect x=\"30\" width=\"380\" height=\"400\" style=\"fill:rgb(255,255,255);\" />"

  @resources %{
    first:  %{collection: [10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11], x: 0, y: 0, height: 400, width: 400},
    second: %{collection: [20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21], x: 0, y: 0, height: 400, width: 400},
    third: %{collection: [30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31], x: 0, y: 0, height: 400 , width: 400},
  }

  @id_to_source %{
    10 => "background_400_400_1.png",
    11 => "background_400_400_2.png",
    # ---
    20 => "skincolor_400_400_1.png",
    21 => "skincolor_400_400_2.png",
    # ---
    30 => "face_400_400_1.png",
    31 => "face_400_400_2.png",
  }

  @keys [:first, :second, :third, :fourth, :fifth, :sixth]

  def get_module_doc, do: @moduledoc

  @spec handle_svg(String.t(), String.t()) :: map()
  def handle_svg(img_raw, base_url) do
    img_parsed =
      URIHandler.decode_uri(img_raw)
    img_handled = do_handle_svg(img_parsed, base_url)
    %{}
    |> Map.put(:image, img_handled)
    |> Map.put(:image_encoded, NFTHandler.encode_uri(img_handled, :svg))

  end

  @spec do_handle_svg(String.t(), String.t()) :: binary
  def do_handle_svg(img_parsed, base_url) do

    abstract_nft =
      img_parsed
      |> parser_svg()
    IO.puts inspect abstract_nft
      # |> insert_background(@resources)
    payload_svg =
      Enum.reduce(@resources, "", fn {key, payload}, svg_acc ->
        # exp. %{collection: [4], x: 1, y: 1, height: 500, width: 500}
        %{collection: collection, x: x, y: y, height: height, width: width} = payload
        value = Map.get(abstract_nft, key)
        IO.puts inspect value
        source =
          collection
          |> Enum.at(value - 1)
          |> handle_img_resource(base_url)


        svg_acc <> build_img_payload(source, x, y, height, width)
      end)

    result =
      img_parsed
      |> insert_payload_to_svg(@traits.n, payload_svg)
      |> replace_header()
      |> insert_white_rect()

    result
  end

  def replace_header(img) do
    String.replace(img, @header.origin, @header.replace)
  end

  def insert_white_rect(img) do
    {pos, _} = :binary.match(img, @traits.img)
    {bef, aft} = String.split_at(img, pos)
    bef <> @rect <> aft
  end


  def build_img_payload(nil, _x, _y, _height, _width), do: nil
  def build_img_payload(source, x, y, height, width) do
    "<image xlink:href='#{source}' "
    |> Kernel.<>("x='#{x}' y='#{y}' ")
    |> Kernel.<>("height='#{height}' width='#{width}' />")
  end


  # def insert_background(abstract_nft, %{background: _background}) do
  #   Map.put(abstract_nft, :background, 1)
  # end

  def parser_svg(img_parsed) do
    value =
      img_parsed
        |> String.split("class=\"base\">")
        |> Enum.drop(1)
        |> Enum.map(&(String.at(&1,0)))
        |> Enum.reject(&(Integer.parse(&1) == :error))
        |> Enum.map(&(String.to_integer(&1)))
    # value
    @keys
    |> Enum.zip(value)
    |> Enum.into(%{})
  end

  def handle_img_resource(unique_id, _base_url) when is_nil(unique_id) or (unique_id == 0), do: ""

  def handle_img_resource(unique_id, base_url) do
    source =
      unique_id
      |> id_to_source()

    base_url
    |> handle_url()
    |> Kernel.<>(source)
  end

  def insert_payload_to_svg(img_svg, trait, payload) do
    {position, _length} =  :binary.match(img_svg, trait)
    {payload_head, payload_tail}
      = String.split_at(img_svg, position)
    payload_head
    |> Kernel.<>(payload)
    |> Kernel.<>(payload_tail)
  end

  def handle_url(""), do: ""
  def handle_url(url) do
    if String.at(url, -1) == "/" do
      url
    else
      url <> "/"
    end
  end

  def id_to_source(unique_id), do: Map.get(@id_to_source, unique_id)

end