defmodule Afinn do @moduledoc """ Sentiment analysis using AFINN word lists. This module provides functions to analyze the sentiment of text using the AFINN lexicon, which assigns sentiment scores to words ranging from -5 (very negative) to +5 (very positive). ## Supported Languages - English (`:en`) - Danish (`:dk`) - Finnish (`:fi`) - French (`:fr`) - Polish (`:pl`) - Swedish (`:sv`) - Turkish (`:tr`) - Emoticons (`:emoticon`) ## Examples iex> Afinn.score("I love this!", :en) 3 iex> Afinn.score_to_words("I love this!", :en) :positive iex> Afinn.score("Terrible product!", :en) -3 iex> Afinn.score_to_words("Terrible product!", :en) :negative """ import Language @doc """ Calculates the sentiment score for the given text. The function tokenizes the input text, matches words against the AFINN dictionary for the specified language, and returns the sum of all sentiment scores. ## Parameters - `text` - The text to analyze (String) - `language` - Language identifier (`:en` for English, `:dk` for Danish, `:fi` for Finnish, `:fr` for French, `:pl` for Polish, `:sv` for Swedish, `:tr` for Turkish, `:emoticon` for Emoticons) ## Returns An integer representing the sentiment score. Positive values indicate positive sentiment, negative values indicate negative sentiment, and zero indicates neutral sentiment. ## Examples iex> Afinn.score("I love Elixir!", :en) 3 iex> Afinn.score("This is bad", :en) -3 iex> Afinn.score("Hello world", :en) 0 """ @spec score(String.t(), :en | :dk | :fi | :fr | :pl | :sv | :tr | :emoticon) :: integer() def score(text, language) do dictionary = read_dictionaries(language) Regex.replace(~r/[!'",.?]/, text, "") |> String.downcase() |> String.split(" ") |> Enum.map(fn x -> Map.get(dictionary, x, 0) end) |> Enum.sum() end @doc """ Converts the sentiment score to a human-readable classification. Classifies the sentiment of the given text as positive, negative, or neutral based on the calculated sentiment score. ## Parameters - `text` - The text to analyze (String) - `language` - Language identifier (`:en` for English, `:dk` for Danish, `:fi` for Finnish, `:fr` for French, `:pl` for Polish, `:sv` for Swedish, `:tr` for Turkish, `:emoticon` for Emoticons) ## Returns An atom representing the sentiment: - `:positive` - for scores greater than 1 - `:negative` - for scores less than -1 - `:neutral` - for scores between -1 and 1 (inclusive) ## Examples iex> Afinn.score_to_words("I love this!", :en) :positive iex> Afinn.score_to_words("I hate this!", :en) :negative iex> Afinn.score_to_words("This is okay", :en) :neutral """ @spec score_to_words(String.t(), :en | :dk | :fi | :fr | :pl | :sv | :tr | :emoticon) :: :positive | :negative | :neutral def score_to_words(text, language) do score = score(text, language) cond do score > 1 -> :positive score < -1 -> :negative score in -1..1 -> :neutral end end end