#include <stdexcept>
#include <iostream>
#include <string>
#include <map>

typedef std::map<std::string, double> map_type ;

const double smoothingFactor = .5 ;

double addDataPoint(map_type & m, map_type::value_type data)
{
    map_type::iterator it = m.find(data.first) ;

    if ( it == m.end() )
    {
        m[data.first] = data.second ;
        return data.second ;
    }

    return it->second = smoothingFactor * data.second + (1-smoothingFactor) * it->second ;
}

double getAverage(const map_type& m, const map_type::key_type & key )
{
    map_type::const_iterator it = m.find(key) ;
    if ( it == m.end() )
        throw std::logic_error( "getAverage called for non-existent key: \"" + key + '"') ;
    return it->second ;
}

std::ostream& operator<<(std::ostream& os, const map_type & map )
{
    map_type::const_iterator it ;
    for ( it = map.begin(); it != map.end(); ++it )
        os << it->first << ": " << it->second << '\n' ;
    return os ;
}

int main()
{
    map_type emaMap ;

    try
    {
        std::cout << "addDataPoint(\"a\", 4)\n" ;
        addDataPoint(emaMap, std::make_pair("a", 4)) ;
        std::cout << emaMap << '\n' ;

        std::cout << "addDataPoint(\"b\", 8)\n" ;
        addDataPoint(emaMap, std::make_pair("b", 8)) ;
        std::cout << emaMap << '\n' ;

        std::cout << "addDataPoint(\"a\", 6)\n" ;
        addDataPoint(emaMap, std::make_pair("a", 6)) ;
        std::cout << emaMap << '\n' ;

        std::cout << "addDataPoint(\"b\", 12)\n" ;
        addDataPoint(emaMap, std::make_pair("b", 12)) ;
        std::cout << emaMap << '\n' ;

        std::cout << "getAverage(\"a\")\n" ;
        std::cout << getAverage(emaMap, "a") << "\n\n" ;

        std::cout << "getAverage(\"b\")\n" ;
        std::cout << getAverage(emaMap, "b") << "\n\n" ;

        std::cout << "getAverage(\"c\")\n" ;
        std::cout << getAverage(emaMap, "c") << "\n\n" ;
    }
    catch (std::exception& ex)
    {
        std::cout << ex.what() << '\n' ;
    }
}
