Compare commits
3 Commits
feature/de
...
5ac1a6c8e7
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ac1a6c8e7 | |||
| 3a2af2adb4 | |||
| b92503d643 |
@ -1,6 +1,6 @@
|
|||||||
alias Outlook.HtmlPreparations
|
alias Outlook.HtmlPreparations
|
||||||
alias Outlook.HtmlPreparations.HtmlPreparation
|
alias Outlook.HtmlPreparations.HtmlPreparation
|
||||||
alias Outlook.InternalTree.{Html,InternalNode,TranslationUnit}
|
alias Outlook.InternalTree.{Html,InternalNode,TranslationUnit,TunitModifications}
|
||||||
alias Outlook.InternalTree
|
alias Outlook.InternalTree
|
||||||
alias Outlook.Articles
|
alias Outlook.Articles
|
||||||
alias Outlook.Accounts
|
alias Outlook.Accounts
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
defmodule Outlook.InternalTree do
|
defmodule Outlook.InternalTree do
|
||||||
|
|
||||||
alias Outlook.InternalTree.{Html,Modifiers,RawInternalBasic,InternalTree,Translation}
|
alias Outlook.InternalTree.{Html,Modifiers,RawInternalBasic,InternalTree,Translation,TunitModifications}
|
||||||
alias Outlook.HtmlPreparations.HtmlPreparation
|
alias Outlook.HtmlPreparations.HtmlPreparation
|
||||||
alias Outlook.{Hyphenation, Translations}
|
alias Outlook.{Hyphenation, Translations}
|
||||||
|
|
||||||
@ -69,6 +69,9 @@ defmodule Outlook.InternalTree do
|
|||||||
|
|
||||||
def get_tunit_ids(tree) do
|
def get_tunit_ids(tree) do
|
||||||
InternalTree.collect_tunit_ids(tree)
|
InternalTree.collect_tunit_ids(tree)
|
||||||
# |> List.flatten()
|
end
|
||||||
|
|
||||||
|
def modify_tunits(tree, modifier, tu_ids) do
|
||||||
|
TunitModifications.apply_modifier(tree, modifier, tu_ids)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
83
lib/outlook/internal_tree/tunit_modifications.ex
Normal file
83
lib/outlook/internal_tree/tunit_modifications.ex
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
defmodule Outlook.InternalTree.TunitModifications do
|
||||||
|
|
||||||
|
alias Outlook.InternalTree.{InternalNode,TranslationUnit}
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def modifiers do
|
||||||
|
[
|
||||||
|
%{
|
||||||
|
name: "unite_with_next",
|
||||||
|
fn: &unite_with_next/2,
|
||||||
|
label: "Unite with next",
|
||||||
|
description: "unite translation unit with next"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
name: "split_tunit",
|
||||||
|
fn: &split_tunit/2,
|
||||||
|
label: "Split Translation unit",
|
||||||
|
description: "split translation unit into two"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Modifier functions
|
||||||
|
|
||||||
|
defp unite_with_next(nodelist, tu_ids) when is_list(tu_ids) do
|
||||||
|
ids_to_process = Enum.reverse(tu_ids)
|
||||||
|
Logger.info "nu: #{inspect tu_ids}"
|
||||||
|
Enum.reduce(ids_to_process, nodelist, fn id, nodes -> unite_with_next(nodes, id) end)
|
||||||
|
end
|
||||||
|
defp unite_with_next(nodelist, tu_id) do
|
||||||
|
ind = Enum.find_index(nodelist, fn n -> n.nid == tu_id end)
|
||||||
|
case Enum.slice(nodelist, ind, 2) do
|
||||||
|
[unit, next] ->
|
||||||
|
nunit = %TranslationUnit{unit | content: unit.content <> next.content}
|
||||||
|
nodelist
|
||||||
|
|> List.replace_at(ind, nunit)
|
||||||
|
|> List.delete_at(ind + 1)
|
||||||
|
[_] ->
|
||||||
|
nodelist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp split_tunit(_nodelist, _tu_ids) do
|
||||||
|
end
|
||||||
|
|
||||||
|
# Function and helpers to apply modifiers
|
||||||
|
|
||||||
|
def apply_modifier([ %InternalNode{} = node | rest ], modifier, tu_ids) when node.type == :element do
|
||||||
|
content = case List.first(node.content) do
|
||||||
|
%TranslationUnit{} -> process_tunit_list(node.content, modifier, tu_ids)
|
||||||
|
_ -> apply_modifier(node.content, modifier, tu_ids)
|
||||||
|
end
|
||||||
|
[%InternalNode{node| content: content} | apply_modifier(rest, modifier, tu_ids)]
|
||||||
|
end
|
||||||
|
def apply_modifier([node, rest], modifier, tu_ids), do: [node | apply_modifier(rest, modifier, tu_ids)]
|
||||||
|
def apply_modifier([],_, _), do: []
|
||||||
|
|
||||||
|
def process_tunit_list(tunits, modifier, tu_ids) do
|
||||||
|
modi_fun = get_modi_fun(modifier)
|
||||||
|
ids_to_process = get_ids_to_process(tunits, tu_ids)
|
||||||
|
case length(ids_to_process) do
|
||||||
|
0 -> tunits
|
||||||
|
_ -> modi_fun.(tunits, ids_to_process)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def get_ids_to_process(tunits, tu_ids) do
|
||||||
|
present_ids = Enum.map(tunits, fn u -> u.nid end)
|
||||||
|
found_ids = MapSet.new(present_ids)
|
||||||
|
|> MapSet.intersection(MapSet.new(tu_ids))
|
||||||
|
|> MapSet.to_list()
|
||||||
|
# make sure to return ids in the order they occur in tunits
|
||||||
|
Enum.filter(present_ids, fn pres -> pres in found_ids end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_modi_fun(modifier) do
|
||||||
|
modifiers()
|
||||||
|
|> Enum.find(fn m -> m.name == modifier end)
|
||||||
|
|> Map.get(:fn)
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -48,19 +48,6 @@ defmodule Outlook.Translators do
|
|||||||
|> Repo.update_all([inc: [our_character_count: billed_characters]])
|
|> Repo.update_all([inc: [our_character_count: billed_characters]])
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_uptodate_deepl_counts(user) do
|
|
||||||
deepl_counts = Deepl.get_usage_counts(get_deepl_auth_key(user))
|
|
||||||
our_character_count = deepl_account_for_user(user)
|
|
||||||
|> select([:our_character_count])
|
|
||||||
|> Repo.one()
|
|
||||||
|> Map.get(:our_character_count)
|
|
||||||
most_accurate = max(our_character_count, deepl_counts.character_count)
|
|
||||||
%{character_limit: deepl_counts.character_limit,
|
|
||||||
character_count: deepl_counts.character_count,
|
|
||||||
our_character_count: our_character_count,
|
|
||||||
percent_used: most_accurate * 100 / deepl_counts.character_limit}
|
|
||||||
end
|
|
||||||
|
|
||||||
def translate(translation, current_user) do
|
def translate(translation, current_user) do
|
||||||
%{language: target_lang,
|
%{language: target_lang,
|
||||||
article: %{content: article_tree, language: source_lang}
|
article: %{content: article_tree, language: source_lang}
|
||||||
@ -84,14 +71,6 @@ defmodule Outlook.Translators do
|
|||||||
process_translation(result.translation, tunit_ids)
|
process_translation(result.translation, tunit_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_deepl_counts(user, counts) do
|
|
||||||
deepl_account_for_user(user)
|
|
||||||
|> Repo.update_all([set: [
|
|
||||||
character_limit: counts.character_limit,
|
|
||||||
character_count: counts.character_count
|
|
||||||
]])
|
|
||||||
end
|
|
||||||
|
|
||||||
defp deepl_account_for_user(user) when is_struct(user), do: deepl_account_for_user(user.id)
|
defp deepl_account_for_user(user) when is_struct(user), do: deepl_account_for_user(user.id)
|
||||||
defp deepl_account_for_user(user_id) do
|
defp deepl_account_for_user(user_id) do
|
||||||
DeeplAccount |> where(user_id: ^user_id)
|
DeeplAccount |> where(user_id: ^user_id)
|
||||||
|
|||||||
@ -31,7 +31,7 @@ defmodule OutlookWeb.ArticleLive.NewComponents do
|
|||||||
<div>Review Raw InternalTree</div>
|
<div>Review Raw InternalTree</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div id="html-preview" class="article">
|
<div id="html-preview" class="article">
|
||||||
<%= InternalTree.render_html_preview(@raw_internal_tree) |> raw %>
|
<.render_doc tree={@raw_internal_tree} ></.render_doc>
|
||||||
</div>
|
</div>
|
||||||
<div id="html-tree">
|
<div id="html-tree">
|
||||||
<.render_tree tree={@raw_internal_tree} ></.render_tree>
|
<.render_tree tree={@raw_internal_tree} ></.render_tree>
|
||||||
|
|||||||
83
test/outlook/internaltree_tunitmodifications_test.exs
Normal file
83
test/outlook/internaltree_tunitmodifications_test.exs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
defmodule Outlook.InternalTreeTest do
|
||||||
|
use Outlook.DataCase
|
||||||
|
|
||||||
|
# import Outlook.InternalTreeTestHelpers
|
||||||
|
|
||||||
|
describe "internal_tree" do
|
||||||
|
alias Outlook.InternalTree
|
||||||
|
alias Outlook.InternalTree.{InternalNode,TranslationUnit}
|
||||||
|
|
||||||
|
def tree() do
|
||||||
|
[
|
||||||
|
%InternalNode{
|
||||||
|
name: "p",
|
||||||
|
attributes: %{},
|
||||||
|
type: :element,
|
||||||
|
nid: "rRIib2h8tyix",
|
||||||
|
content: [
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "GuU9v6xeSS7e", content: "Joe Biden a.", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "bzCLsYGNe2PG", content: "k.", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "GyRUrzwH9LcP", content: "a. ", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "y2yb38U4hkya", content: "Crash Test Dummy.", eph: %{}}
|
||||||
|
],
|
||||||
|
eph: %{sibling_with: :block}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "unite_with_next unites with next in simple case" do
|
||||||
|
assert InternalTree.modify_tunits(tree(), "unite_with_next", ["bzCLsYGNe2PG"]) == [
|
||||||
|
%InternalNode{
|
||||||
|
name: "p",
|
||||||
|
attributes: %{},
|
||||||
|
type: :element,
|
||||||
|
nid: "rRIib2h8tyix",
|
||||||
|
content: [
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "GuU9v6xeSS7e", content: "Joe Biden a.", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "bzCLsYGNe2PG", content: "k.a. ", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "y2yb38U4hkya", content: "Crash Test Dummy.", eph: %{}}
|
||||||
|
],
|
||||||
|
eph: %{sibling_with: :block}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "unite_with_next unites all with next in complex case" do
|
||||||
|
assert InternalTree.modify_tunits(tree(), "unite_with_next", ["GuU9v6xeSS7e","bzCLsYGNe2PG","GyRUrzwH9LcP"]) == [
|
||||||
|
%InternalNode{
|
||||||
|
name: "p",
|
||||||
|
attributes: %{},
|
||||||
|
type: :element,
|
||||||
|
nid: "rRIib2h8tyix",
|
||||||
|
content: [
|
||||||
|
%TranslationUnit{
|
||||||
|
status: :untranslated,
|
||||||
|
nid: "GuU9v6xeSS7e",
|
||||||
|
content: "Joe Biden a.k.a. Crash Test Dummy.",
|
||||||
|
eph: %{}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
eph: %{sibling_with: :block}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "unite_with_next ignores id if there is no next tunit" do
|
||||||
|
assert InternalTree.modify_tunits(tree(), "unite_with_next", ["y2yb38U4hkya"]) == [
|
||||||
|
%InternalNode{
|
||||||
|
name: "p",
|
||||||
|
attributes: %{},
|
||||||
|
type: :element,
|
||||||
|
nid: "rRIib2h8tyix",
|
||||||
|
content: [
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "GuU9v6xeSS7e", content: "Joe Biden a.", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "bzCLsYGNe2PG", content: "k.", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "GyRUrzwH9LcP", content: "a. ", eph: %{}},
|
||||||
|
%TranslationUnit{status: :untranslated, nid: "y2yb38U4hkya", content: "Crash Test Dummy.", eph: %{}}
|
||||||
|
],
|
||||||
|
eph: %{sibling_with: :block}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user