﻿//var siteAddress = 'http://localhost/LastfmSongStatistics/';
var siteAddress = 'http://lastfm.heathaze.org/';
var xmlHtppReq;
//var pbXmlHtppReq;
var clockIntervalId;
var reqId;
var pg;

//The recommendation data
var rd;

function createXmlHttpInstance()
{
    //Create XMLHttpRequest instance
    if (window.XMLHttpRequest)
        xmlHtppReq = new XMLHttpRequest();
    else if (window.ActiveXObject)
        xmlHtppReq = new ActiveXObject("Microsoft.XMLHTTP");
    else
    {
        alert('No XmlHttp Support');
        return;
    }
}

//Main method. Posts to server to get the data.
function getRSF(e, page)
{
    pg = page;
    
    //Handle Enter Key
    if (e != null)
    {
        var keynum;
        if(window.event) // IE
            keynum = e.keyCode;
        else if(e.which) // Netscape/Firefox/Opera
            keynum = e.which;
        
        if (keynum != 13)
            return;
    }
   
    //Initialize XmlHttp
    createXmlHttpInstance();
   
    //Send request
    reqId = new Date().valueOf();
    var goUrl = siteAddress + page + '.aspx?userName=' + document.form1.txtUserName.value;
    xmlHtppReq.onreadystatechange = xmlhttpStateChange;
    xmlHtppReq.open("GET", goUrl, true );
    xmlHtppReq.setRequestHeader("ajaxClient","true");
    xmlHtppReq.setRequestHeader("timestamp", reqId);
    if (page == 'recommendations')
    {
        if (document.getElementById('rdoBySimilarTracks').checked)
        {
            xmlHtppReq.setRequestHeader("recType","REC_BST");
            xmlHtppReq.setRequestHeader("maxSongs",document.getElementById('selBySimilarTracks').value);
        }
        else
        {
            xmlHtppReq.setRequestHeader("recType","REC_BNT");
            xmlHtppReq.setRequestHeader("maxSongs",document.getElementById('selByNeighborTopTracks').value);
        }
    }
    xmlHtppReq.send(null);
    
    //Hide error bar
    hideError();
    
    //Start clock
    //startClock();
    
    //Start progress bar.
    startProgressBar();
}

function xmlhttpStateChange()
{
    if (xmlHtppReq.readyState==4)
    {
        if (xmlHtppReq.status==200)
        {
            //Stop and clear the progress bar
            clearProgressBar();
            
            //clearClock();
            
            //Load the return data to xml and set the appropriate nodes
            var xmlDoc = loadXMLString(xmlHtppReq.responseText);
            
            var errorMessageNode = xmlDoc.getElementsByTagName('errorMessage');
            //Error
            if (errorMessageNode.length > 0)
            {
                showError(errorMessageNode[0].childNodes[0].nodeValue);
            }
            //Normal
            else
            {
                if (pg == 'recommendations')
                {
                    //Clear earlier recos
                    clearRecos();
                    
                    //Display the new recos
                    displayRecos(xmlDoc);
                }
                else
                {
                    //Clear result pane
                    clearResults();
                
                    //Show new results
                    displayResults(xmlDoc);
                }
            }
        }
        else
        {
            //Have no shame. Show crash!
            document.write(xmlHtppReq.responseText);
        }
    }
}

function loadXMLString(txt) 
{
    var xmlDoc;
    try //Internet Explorer
    {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = "false";
        xmlDoc.loadXML(txt);
    }
    catch(e)
    {
        try //Firefox, Mozilla, Opera, etc.
        {
            parser = new DOMParser();
            xmlDoc = parser.parseFromString(txt, "text/xml");
        }
        catch(e)
        {
            showError(e.message);
        }
    }
    //showAllMethods(xmlDoc);
    return xmlDoc;
}

//DEBUG
function showAllMethods(obj)
{
    var methods = new Array();

    for (var s in obj)
    {
        methods[methods.length] = s;
        alert(s);
    }

    return methods;
}

function doProgressBar()
{
    //Create XMLHttpRequest instance for progress bar
    if (window.XMLHttpRequest)
        pbXmlHtppReq = new XMLHttpRequest();
    else if (window.ActiveXObject)
        pbXmlHtppReq = new ActiveXObject("Microsoft.XMLHTTP");
    else
    {
        showError('No XmlHttp Support.');
        return;
    }
    
    var suffix = '';
    if (pg == 'recommendations')
        suffix = '_reco';
    
    //Send progress bar request
    var goUrl = siteAddress + 'temp/' + document.form1.txtUserName.value + "_" + reqId + suffix + ".txt";
    //alert(goUrl);
    pbXmlHtppReq.onreadystatechange = pbXmlhttpStateChange;
    pbXmlHtppReq.open("GET", goUrl, true );
    pbXmlHtppReq.send(null);
}

function pbXmlhttpStateChange()
{
    if (pbXmlHtppReq.readyState==4)
    {
        //Received the progress bar response. Process it.
        if (pbXmlHtppReq.status==200)
        {
            //Read the completion percentage from response
            var pctComplete = parseFloat(pbXmlHtppReq.responseText);
            if (isNaN(pctComplete))
                return;
            
            //Round                    
            pctComplete = Math.round(pctComplete);
            
            //Set the width and text of progress bar
            document.getElementById('progressVal').innerHTML = pctComplete + '%';
            document.getElementById('progressbarl').style.width = pctComplete + '%';
        }
        else
        {
            //alert(pbXmlHtppReq.statusText);
            //Expected error 404. If no ajax file has been written yet.
        }
        
        //keep posting to server for progress
        setTimeoutId = setTimeout("doProgressBar()", 1000);
    }
}


function clearProgressBar()
{
    //Stop timer
    clearTimeout(setTimeoutId);
    
    //Set the progress back to 0%
    document.getElementById('progressbarl').style.width = '0%';
    document.getElementById('progressbarr').style.width = '100%';
    document.getElementById('progressVal').innerHTML = '0%';
    
    //Collapse progress bar
    document.getElementById('progressbarDiv').style.display = 'none';
}

function startProgressBar()
{
    document.getElementById('progressbarl').style.width = '0%';
    document.getElementById('progressbarr').style.width = '100%';
    document.getElementById('progressVal').innerHTML = '0%';
    document.getElementById('progressbarDiv').style.display = '';
    
    //start posting to server for progress
    setTimeoutId = setTimeout("doProgressBar()", 1000);
}

//function startClock()
//{
//    document.getElementById('divProgress').style.display = 'block';
//    document.getElementById('divTimeElapsed').innerHTML = 0;
//    clockIntervalId = setInterval('updateClock()', 1000 );
//}

//function updateClock()
//{
//    var now = parseInt(document.getElementById('divTimeElapsed').innerHTML);
//    document.getElementById('divTimeElapsed').innerHTML = now + 1;
//}

//function clearClock()
//{
//    clearInterval(clockIntervalId);
//    document.getElementById('divTimeElapsed').innerHTML = 0;
//    document.getElementById('divProgress').style.display = 'none';
//}

function showError(errorMessage)
{
    document.getElementById('errorMsgDiv').style.display = '';
    document.getElementById('errorMsgBar').innerHTML = errorMessage;
}

function hideError()
{
    document.getElementById('errorMsgDiv').style.display = 'none';
    document.getElementById('errorMsgBar').innerHTML = ' ';
}

////////////////////////////////////////////////////////////////RECOMMENDATION SONG STATS//////////////////////////////////////////////////

function RecoRow(song, artist, score)
{
    this.song = song;
    this.artist = artist;
    this.score = score;
    return true;
}

function RecoData(len)
{
    this.listByScore = new Array(len);
    this.listByArtist = new Array(len);
    this.lsIndex = 0;
    this.laIndex = 0;
    this.showing = 'resultPanelActualBySong';
    this.length = len;
    this.totalDivs = 0;
    return true;
}


function displayRecos(xmlDoc)
{
    var recoInfoBySong = xmlDoc.getElementsByTagName('recoInfoBySong')[0];
    var recoInfoByArtist = xmlDoc.getElementsByTagName('recoInfoByArtist')[0];
    var len = recoInfoByArtist.getElementsByTagName('RecRow').length;
    rd = new RecoData(len);
    
    populateTheRecoTables(recoInfoBySong, 'BS');
    populateTheRecoTables(recoInfoByArtist, 'BA');
    
    //Show result panel
    document.getElementById('resultPanel').style.display = '';
}

function populateTheRecoTables(rootRecoInfoNode, difftor)
{
    var recNodes = rootRecoInfoNode.getElementsByTagName('RecRow');
    var songNodes = rootRecoInfoNode.getElementsByTagName('Key');
    var artistNodes = rootRecoInfoNode.getElementsByTagName('artist');
    
    var profileCode = (difftor == 'BS') ?
                     '[url=http://lastfm.heathaze.org][size=10][b]Recommended Songs (sorted by most recommended songs)[/b][/size][/url]\n\n' :
                     '[url=http://lastfm.heathaze.org][size=10][b]Recommended Songs (sorted by most recommended artists)[/b][/size][/url]\n\n';
    
    var i=0;
    var theList = (difftor == 'BS') ? rd.listByScore : rd.listByArtist;

    //Populate the list of RecoData
    for (i=0; i<rd.length; i++)
    {
            var artist = artistNodes[i].attributes[0].value;
            var song = songNodes[i].attributes[0].value;
            var score = Math.round(parseFloat(recNodes[i].attributes[0].value) * 100) / 100;
            theList[i] = new RecoRow(song, artist, score);
            
            if (i < 100)
                profileCode = profileCode + '[track artist=' + artist + ']' + song + '[/track]  :  [artist]' + artist + '[/artist] (Score = ' + score + ')\n';
    }

    var MAX_ROWS = 25;
    var divsNeeded = (rd.length % MAX_ROWS > 0) ? (rd.length / MAX_ROWS + 1) : (rd.length / MAX_ROWS);
    rd.totalDivs = divsNeeded;
    for (i=0; i<divsNeeded; i++)
    {
        //create the dynamic div
        var dynRecoDiv = document.createElement('div');
        dynRecoDiv.Id = 'dynRecoDiv' + difftor + i;
        
        //create the table to be put inside div
        var dynRecoTbl = document.createElement('table');
        dynRecoTbl.style.width = '100%';
        dynRecoTbl.className = 'topmonthlytable';
        
        //Header of table
        var thead = dynRecoTbl.createTHead();
        var thTr = thead.insertRow(-1);
        var tdSongH = thTr.insertCell(-1); tdSongH.innerHTML = 'Song'; setStyleOfTd(tdSongH); tdSongH.style.fontWeight = 'bold';
        var tdArtistH = thTr.insertCell(-1); tdArtistH.innerHTML = 'Artist'; setStyleOfTd(tdArtistH); tdArtistH.style.fontWeight = 'bold';
        var tdRecScoreH = thTr.insertCell(-1); tdRecScoreH.innerHTML = 'Recommendation Score'; setStyleOfTd(tdRecScoreH); tdRecScoreH.style.fontWeight = 'bold';
        var tdAmazonSrchH = thTr.insertCell(-1); tdAmazonSrchH.innerHTML = 'Find on Amazon'; setStyleOfTd(tdAmazonSrchH); tdAmazonSrchH.style.fontWeight = 'bold';
        var tdSpotifyH = thTr.insertCell(-1); tdSpotifyH.innerHTML = 'Spotify Search'; setStyleOfTd(tdSpotifyH); tdSpotifyH.style.fontWeight = 'bold';
        
        //Populate the table with MAX_ROWS recs atmost
        var j = 0;
        for (j = 0; (j < MAX_ROWS) && ((i*MAX_ROWS + j) < rd.length); j++)
        {
            var tr = dynRecoTbl.insertRow(-1);
            
            var tdSong = tr.insertCell(-1);
            setStyleOfTd(tdSong);
            tdSong.innerHTML = theList[(i*MAX_ROWS + j)].song;
            
            var tdArtist = tr.insertCell(-1);
            setStyleOfTd(tdArtist);
            tdArtist.innerHTML = theList[(i*MAX_ROWS + j)].artist;
            
            var tdScore = tr.insertCell(-1);
            setStyleOfTd(tdScore);
            tdScore.innerHTML = theList[(i*MAX_ROWS + j)].score;
            
            var tdAmazon = tr.insertCell(-1);
            setStyleOfTd(tdAmazon);
            tdAmazon.innerHTML = '<a href="javascript:openAmazonSearchDiv(\'' + theList[(i*MAX_ROWS + j)].artist.replace('\'', '\\\'') + '\', \'' + theList[(i*MAX_ROWS + j)].song.replace('\'', '\\\'') + '\');">Find</a>';
            
            var tdSpotify = tr.insertCell(-1);
            setStyleOfTd(tdSpotify);
            tdSpotify.innerHTML = '<a href="http://open.spotify.com/search/artist:%22' + theList[(i*MAX_ROWS + j)].artist + '%22%20title:%22' + theList[(i*MAX_ROWS + j)].song + '%22" target="_new">Search</a>';
        }
        
        //Add table with MAX_ROWS recs into dynamic div
        dynRecoDiv.appendChild(dynRecoTbl);
        
        //Only show first div
        if (i > 0)
            dynRecoDiv.style.display = 'none';
        
        //Add dynamic div into resultPanelActualBySong
        if (difftor == 'BS')
            document.getElementById('resultPanelActualBySong').appendChild(dynRecoDiv);
        else
            document.getElementById('resultPanelActualByArtist').appendChild(dynRecoDiv);
            
        //Profile Code
        var theTextBox = document.getElementById('profileRecs' + difftor);
        theTextBox.value = profileCode;
    }
}

function clearRecos()
{
    var resultPanel = document.getElementById('resultPanel').style.display = 'none';
    document.getElementById('resultPanelActualBySong').innerHTML = '';
    document.getElementById('resultPanelActualByArtist').innerHTML = '';
}

function doRecoPagePrevNext(dir)
{
    var topDiv = document.getElementById(rd.showing);
    var theDivColl = topDiv.getElementsByTagName('div');
    
    if (rd.showing == 'resultPanelActualBySong')
    {
        if (dir < 0 && rd.lsIndex == 0) return;
        if (dir > 0 && rd.lsIndex == rd.totalDivs - 1) return;
        theDivColl[rd.lsIndex].style.display = 'none';
        rd.lsIndex += dir;
        theDivColl[rd.lsIndex].style.display = 'block';
    }
    else
    {
        if (dir < 0 && rd.laIndex == 0) return;
        if (dir > 0 && rd.laIndex == rd.totalDivs - 1) return;
        theDivColl[rd.laIndex].style.display = 'none';
        rd.laIndex += dir;
        theDivColl[rd.laIndex].style.display = 'block';
    }
}

function toggleRecSortType()
{
    var topDiv = document.getElementById(rd.showing);
    topDiv.style.display = 'none';
    
    if (rd.showing == 'resultPanelActualBySong')
    {
        topDiv.getElementsByTagName('div')[rd.lsIndex].style.display = 'none';
        rd.showing = 'resultPanelActualByArtist';
        document.getElementById('linkRecoSort').innerHTML = 'Sort By Most Recommended Songs';
    }
    else
    {
        topDiv.getElementsByTagName('div')[rd.laIndex].style.display = 'none';
        rd.showing = 'resultPanelActualBySong';
        document.getElementById('linkRecoSort').innerHTML = 'Sort By Most Recommended Artists';
    }

    rd.laIndex = 0;
    rd.lsIndex = 0;
    
    topDiv = document.getElementById(rd.showing);
    topDiv.style.display = 'block';
    topDiv.getElementsByTagName('div')[0].style.display = 'block';
}

////////////////////////////////////////////////////////////////RANDOM SONG STATS//////////////////////////////////////////////////

function displayResults(xmlDoc)
{
    //SRI and UTL
    var resultPanel = document.getElementById('resultPanel');
    resultPanel.style.display = '';

    document.getElementById('lblTsl').innerHTML = xmlDoc.getElementsByTagName('totalSongs')[0].childNodes[0].nodeValue;
    document.getElementById('lblTusl').innerHTML = xmlDoc.getElementsByTagName('uniqueSongs')[0].childNodes[0].nodeValue;
    document.getElementById('lblSri').innerHTML = xmlDoc.getElementsByTagName('sri')[0].childNodes[0].nodeValue;
    
    //Display the images
    var linkSri = document.createElement('img');
    linkSri.setAttribute('src', xmlDoc.getElementsByTagName('sriImagePath')[0].childNodes[0].nodeValue);
    linkSri.setAttribute('id', 'linkSri');
    document.getElementById('imgSri').appendChild(linkSri);
    
    var linkUtl = document.createElement('img');
    linkUtl.setAttribute('src', xmlDoc.getElementsByTagName('utlImagePath')[0].childNodes[0].nodeValue);
    linkUtl.setAttribute('id', 'linkUtl');
    document.getElementById('imgTusl').appendChild(linkUtl);
    
    //Profile code for images
    document.getElementById('profileUtlSri').value =
        '[url=' + siteAddress + '][img]' + siteAddress + xmlDoc.getElementsByTagName('sriImagePath')[0].childNodes[0].nodeValue +
        '[/img][/url]\n[url=' + siteAddress + '][img]' + siteAddress +
        xmlDoc.getElementsByTagName('utlImagePath')[0].childNodes[0].nodeValue + '[/img][/url]';
    
    //TMA
    document.getElementById('tmaResultPanel').style.display = '';
    var tmaNode = xmlDoc.getElementsByTagName('topMonthlyArtists')[0];
    var tmaTable = document.getElementById('tmaResultPanelActualTbl');
    var tmaProfileCode = '[url=http://lastfm.heathaze.org][size=10][b]Monthly Top Artists[b][/size][/url]\n\n';
    for (var i=0; i<tmaNode.childNodes.length; i++)
    {
        if (tmaNode.childNodes[i].nodeName != '#text')
        {
            var tr = tmaTable.insertRow(-1);
            
            var tdMonth = tr.insertCell(-1);
            setStyleOfTd(tdMonth);
            tdMonth.innerHTML = tmaNode.childNodes[i].getElementsByTagName('monthName')[0].childNodes[0].nodeValue;
            
            var tdAorS = tr.insertCell(-1);
            setStyleOfTd(tdAorS);
            tdAorS.innerHTML = tmaNode.childNodes[i].getElementsByTagName('artistOrSongName')[0].childNodes[0].nodeValue;
            
            var tdCount = tr.insertCell(-1);
            setStyleOfTd(tdCount);
            tdCount.innerHTML = tmaNode.childNodes[i].getElementsByTagName('count')[0].childNodes[0].nodeValue;
            
            tmaProfileCode = tmaProfileCode + '[b]' + tdMonth.innerHTML + '[/b]\n[artist]' + tdAorS.innerHTML + '[/artist] ([b]' + tdCount.innerHTML + '[/b] plays)\n';
        }
    }
    
    //Profile code for TMA
    document.getElementById('profileTma').value = tmaProfileCode;
    
    
    //TMs
    document.getElementById('tmsResultPanel').style.display = '';
    var tmsNode = xmlDoc.getElementsByTagName('topMonthlySongs')[0];
    var tmsTable = document.getElementById('tmsResultPanelActualTbl');
    var tmsProfileCode = '[url=http://lastfm.heathaze.org][size=10][b]Monthly Top Tracks[b][/size][/url]\n\n';
    for (var i=0; i<tmsNode.childNodes.length; i++)
    {
        if (tmsNode.childNodes[i].nodeName != '#text')
        {
            var tr = tmsTable.insertRow(-1);
            
            var tdMonth = tr.insertCell(-1);
            setStyleOfTd(tdMonth);
            tdMonth.innerHTML = tmsNode.childNodes[i].getElementsByTagName('monthName')[0].childNodes[0].nodeValue;
            
            var tdAorS = tr.insertCell(-1);
            setStyleOfTd(tdAorS);
            tdAorS.innerHTML = tmsNode.childNodes[i].getElementsByTagName('artistOrSongName')[0].childNodes[0].nodeValue;
            
            var tdCount = tr.insertCell(-1);
            setStyleOfTd(tdCount);
            tdCount.innerHTML = tmsNode.childNodes[i].getElementsByTagName('count')[0].childNodes[0].nodeValue;
            
            var splits = tdAorS.innerHTML.split(' : ');
            tmsProfileCode = tmsProfileCode + '[b]' + tdMonth.innerHTML + '[/b]\n[artist]' + splits[0] + '[/artist] : [track artist=' + splits[0] + ']' + splits[1] + '[/track] ([b]' + tdCount.innerHTML + '[/b] plays)\n';
            
            
        }
    }
    
    //Profile code for TMA
    document.getElementById('profileTms').value = tmsProfileCode;
}

function clearResults()
{
    //SRI and UTL
    var resultPanel = document.getElementById('resultPanel');
    resultPanel.style.display = 'none';

    var linkSri = document.getElementById('linkSri');
    if (linkSri != null)
        document.getElementById('imgSri').removeChild(linkSri);

    var linkUtl = document.getElementById('linkUtl');
    if (linkUtl != null)
        document.getElementById('imgTusl').removeChild(linkUtl);
        
    document.getElementById('profileUtlSri').value = '';
    
    //TMA    
    document.getElementById('tmaResultPanel').style.display = 'none';
    var tmaTable = document.getElementById('tmaResultPanelActualTbl');
    for (var i=0; i<tmaTable.childNodes.length; i++)
        if (tmaTable.childNodes[i].nodeName == 'tbody' || tmaTable.childNodes[i].nodeName == 'TBODY')
            tmaTable.removeChild(tmaTable.childNodes[i]);
            
    //TMS
    document.getElementById('tmsResultPanel').style.display = 'none';
    var tmaTable = document.getElementById('tmsResultPanelActualTbl');
    for (var i=0; i<tmaTable.childNodes.length; i++)
        if (tmaTable.childNodes[i].nodeName == 'tbody' || tmaTable.childNodes[i].nodeName == 'TBODY')
            tmaTable.removeChild(tmaTable.childNodes[i]);                    
}


/////////////////////////////////////////////////////////////AMAZON////////////////////////////////////
function openAmazonSearchDiv(a, s)
{
    //Show the div
    var theDiv = document.getElementById('buyAtAmazon');
    theDiv.style.display = 'block';
    
    var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
    
    //Capture scroll event
//    window.onscroll = function () {
//        theDiv.style.top = (scrollTop + (0.3 * document.documentElement.clientHeight)) + 'px';
//    };
    
    //Place it in the middle
    theDiv.style.top = scrollTop + (0.3 * document.documentElement.clientHeight) + 'px';
    theDiv.style.left = 0.3 * document.documentElement.clientWidth + 'px';

    //Show waiting
    document.getElementById('tdWait').innerHTML = 'Searching.....Please Wait...';
    document.getElementById('dgAlb').innerHTML = '';
    document.getElementById('dgMp3').innerHTML = '';
    
    //Get the data
    getAmazonData(a, s);
}

function closeAmazonSearchDiv()
{
    document.getElementById('buyAtAmazon').style.display = 'none';
}

function getAmazonData(artist, song)
{
    //Initialize XmlHttp
    createXmlHttpInstance();
    
    var goUrl = siteAddress + 'buyAtAmazon.aspx';
    
    //Send request
    xmlHtppReq.onreadystatechange = amazonXmlhttpStateChange;
    xmlHtppReq.open("GET", goUrl, true );
    xmlHtppReq.setRequestHeader("ajaxClient", "true");
    xmlHtppReq.setRequestHeader("artist", artist);
    xmlHtppReq.setRequestHeader("song", song);
    xmlHtppReq.setRequestHeader("userName", document.form1.txtUserName.value);
    xmlHtppReq.send(null);
}

function amazonXmlhttpStateChange()
{
    if (xmlHtppReq.readyState==4)
    {
        if (xmlHtppReq.status==200)
        {
            var xmlDoc = loadXMLString(xmlHtppReq.responseText);
            
            document.getElementById('tdWait').innerHTML = '';
            document.getElementById('dgMp3').innerHTML = xmlDoc.getElementsByTagName('mp3GridHtml')[0].childNodes[0].nodeValue;
            document.getElementById('dgAlb').innerHTML = xmlDoc.getElementsByTagName('albumGridHtml')[0].childNodes[0].nodeValue;
        }
        else
        {
            //Have no shame. Show crash
            document.write(xmlHtppReq.responseText);
        }
    }
}


/////////////////////////////////////////////////////////////HELPER METHODS//////////////////////////////////////////

function toggleDiv(divId)
{
    var div = document.getElementById(divId);
    if (div.style.display == 'none')
        div.style.display = '';
    else
        div.style.display = 'none';
}

function setStyleOfTd(theTD)
{
    theTD.style.fontWeight = 'normal';
    theTD.style.borderWidth = '1px';
    theTD.style.borderStyle = 'solid';
    theTD.style.borderColor = '#EEEEEE';
}

