Package com.salas.bb.core

Source Code of com.salas.bb.core.ScoresCalculator$Calculator

// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: ScoresCalculator.java,v 1.15 2008/02/28 15:59:49 spyromus Exp $
//

package com.salas.bb.core;

import com.salas.bb.domain.DataFeed;
import com.salas.bb.domain.DirectFeed;
import com.salas.bb.domain.IFeed;
import com.salas.bb.domain.SearchFeed;
import com.salas.bb.domain.prefs.StarzPreferences;
import com.salas.bb.utils.Constants;
import com.salas.bb.utils.concurrency.CachingCalculator;

import java.beans.PropertyChangeEvent;

/**
* Calculator of different scores for the feed.
*/
public final class ScoresCalculator
{
    private double                  activityWeight;
    private double                  inlinksWeight;
    private double                  clickthroughsWeight;
    private double                  feedViewsWeight;
    private int                     topActivity;

    private static int              maxClickthroughs = 0;
    private static int              maxFeedViews = 0;

    /**
     * Creates calculator.
     */
    ScoresCalculator()
    {
        initThreading();
        loadPreferences(null);
    }

    /**
     * Registers and updates the max feed views (if current value is lower).
     *
     * @param views number of views.
     *
     * @return <code>TRUE</code> if updated the value.
     */
    public static synchronized boolean registerMaxFeedViews(int views)
    {
        boolean updated = false;

        if (maxFeedViews < views)
        {
            maxFeedViews = views;
            updated = true;
        }

        return updated;
    }

    /**
     * Registers and updates the max clickthroughs (if current value is lower).
     *
     * @param clicks number of views.
     *
     * @return <code>TRUE</code> if updated the value.
     */
    public static synchronized boolean registerMaxClickthroughs(int clicks)
    {
        boolean updated = false;

        if (maxClickthroughs < clicks)
        {
            maxClickthroughs = clicks;
            updated = true;
        }

        return updated;
    }

    /**
     * Calculates final score.
     *
     * @param feed   feed to calculate score for.
     *
     * @return score.
     */
    public int calcFinalScore(IFeed feed)
    {
        int score = -1;
        if (feed instanceof DataFeed)
        {
            score = 0;
            if (((DataFeed)feed).isInitialized())
            {
                score = getRatingOfFeed(feed);
            }
        } else if (feed instanceof SearchFeed)
        {
            score = getRatingOfFeed(feed);
        }

            return score;
    }

    private int getRatingOfFeed(IFeed feed)
    {
        int rating = feed.getRating();
        if (rating == -1)
        {
            rating = feed instanceof SearchFeed ? IFeed.RATING_MAX : calcBlogStarzScore(feed);
        }

        return rating;
    }

    /**
     * Calculates BlogStarz score.
     *
     * @param feed feed to calculte the score for.
     *
     * @return the score.
     */
    public int calcBlogStarzScore(IFeed feed)
    {
        return (Integer)calculator.getValue(feed);
    }

    private int calculateTheScore(IFeed feed)
    {
        int score;

        double activity = (feed instanceof DataFeed) ? calcActivity((DataFeed)feed) : -1;
        double inlinks = (feed instanceof DirectFeed) ? calcInlinks((DirectFeed)feed) : -1;
        double clickthroughs = calcClickthroughsScore(feed);
        double feedViews = calcFeedViewsScore(feed);

        double calcInlinksWeight = inlinks > -1 ? inlinksWeight : 0;
        double calcActivityWeight = activity > -1 ? activityWeight : 0;
        double totalWeight = calcActivityWeight + calcInlinksWeight +
            clickthroughsWeight + feedViewsWeight;

        score = (int)((
            activity * calcActivityWeight +
            inlinks * calcInlinksWeight +
            clickthroughs * clickthroughsWeight +
            feedViews * feedViewsWeight) * 4 / totalWeight);

        return score;
    }

    /**
     * Calculates the clickthroughs score.
     *
     * @param feed feed.
     *
     * @return score.
     */
    public double calcClickthroughsScore(IFeed feed)
    {
        return maxClickthroughs == 0 ? 0 : (double)feed.getClickthroughs() / maxClickthroughs;
    }

    /**
     * Calculates the feed views score.
     *
     * @param feed feed.
     *
     * @return score.
     */
    public double calcFeedViewsScore(IFeed feed)
    {
        return maxFeedViews == 0 ? 0 : (double)feed.getViews() / maxFeedViews;
    }

    /**
     * Calculates importance score for the feed.
     *
     * @param feed   feed.
     *
     * @return score.
     */
    public double calcInlinksScore(DirectFeed feed)
    {
        return feed.isInitialized() ? calcInlinks(feed) : 0;
    }

    /**
     * Calculate feed interest score in range [0;1] or -1 if not initialized.
     *
     * @param feed feed to compute score for.
     *
     * @return interest score.
     */
    private double calcInlinks(DirectFeed feed)
    {
        return calcInlinksScore(feed.getInLinks());
    }

    /**
     * Converts inbound links count into a score value in range [0:1].
     *
     * @param inboundLinks number of links.
     *
     * @return score.
     */
    public static double calcInlinksScore(int inboundLinks)
    {
        double aResult = -1;
        if (inboundLinks >= 0)
        {
            if (inboundLinks < 100)
            {
                aResult = 0;
            } else if (inboundLinks < 250)
            {
                aResult = 0.25;
            } else if (inboundLinks < 1000)
            {
                aResult = 0.5;
            } else if (inboundLinks < 2000)
            {
                aResult = 0.75;
            } else
            {
                aResult = 1;
            }
        }
        return aResult;
    }

    /**
     * Calculates pure feed activity in range [0;1].
     *
     * @param feed feed to compute score for.
     *
     * @return feed activity.
     */
    public double calcActivity(DataFeed feed)
    {
        double activity = 0;

        int total = feed.getTotalPolledArticles();
        long initTime = feed.getInitTime();

        if (initTime > 0 && total > 0)
        {
            long time = System.currentTimeMillis();

            activity = ((double)total / (time - initTime)) /
                ((double)topActivity / Constants.MILLIS_IN_DAY);

            if (activity > 1) activity = 1;
        }

        return activity;
    }

    // ---------------------------------------------------------------------------------------------
    // Recalculation
    // ---------------------------------------------------------------------------------------------

    private Calculator      calculator;

    // Initializes multi-threaded calculator
    private void initThreading()
    {
        calculator = new Calculator(1);
    }

    /**
     * Marks cached score value for this feed as invalid and starts immediate background
     * recalculation. If feed wasn't calculated yet new cache record will be created.
     *
     * @param feed feed to invalidate.
     */
    public void invalidateFeed(IFeed feed)
    {
        calculator.invalidateKey(feed);
    }

    /**
     * Marks whole cache as invalid and starts background recalculation of all previously
     * calculated channels.
     */
    public void invalidateAll()
    {
        calculator.invalidateAll();
    }

    /**
     * Called when some feed no longer need the score to be cached.
     *
     * @param feed feed deleted.
     */
    public void feedRemoved(IFeed feed)
    {
        calculator.removeKey(feed);
    }

    /**
     * Load initial preferences.
     *
     * @param prefs prefs.
     */
    public void loadPreferences(StarzPreferences prefs)
    {
        if (prefs == null)
        {
            activityWeight = -1;
            inlinksWeight = -1;
            clickthroughsWeight = -1;
            feedViewsWeight = -1;

            topActivity = -1;
        } else
        {
            activityWeight = prefs.getActivityWeight();
            inlinksWeight = prefs.getInlinksWeight();
            clickthroughsWeight = prefs.getClickthroughsWeight();
            feedViewsWeight = prefs.getFeedViewsWeight();

            topActivity = prefs.getTopActivity();
        }

        invalidateAll();
    }

    /**
     * Listens to changes in properties.
     *
     * @param evt event object.
     *
     * @return TRUE if event was dispatched.
     */
    public boolean dispatchPropertyChangeEvent(PropertyChangeEvent evt)
    {
        String prop = evt.getPropertyName();
        final Object source = evt.getSource();
        boolean invalidate = false;

        if (source instanceof StarzPreferences)
        {
            StarzPreferences prefs = (StarzPreferences)source;

            if (StarzPreferences.PROP_ACTIVITY_WEIGHT.equals(prop))
            {
                activityWeight = prefs.getActivityWeight();
                invalidate = true;
            } else if (StarzPreferences.PROP_INLINKS_WEIGHT.equals(prop))
            {
                inlinksWeight = prefs.getInlinksWeight();
                invalidate = true;
            } else if (StarzPreferences.PROP_TOP_ACTIVITY.equals(prop))
            {
                topActivity = prefs.getTopActivity();
                invalidate = true;
            } else if (StarzPreferences.PROP_CLICKTHROUGHS_WEIGHT.equals(prop))
            {
                clickthroughsWeight = prefs.getClickthroughsWeight();
                invalidate = true;
            } else if (StarzPreferences.PROP_FEED_VIEWS_WEIGHT.equals(prop))
            {
                feedViewsWeight = prefs.getFeedViewsWeight();
                invalidate = true;
            }

            if (invalidate) invalidateAll();
        }
       
        return invalidate;
    }

    /**
     * Simple calculator of the channel scores.
     */
    private class Calculator extends CachingCalculator
    {
        public Calculator(int threads)
        {
            super(threads);
            startThreads();
        }

        protected String getThreadsBaseName()
        {
            return "SC";
        }

        protected Object calculate(Object key)
        {
            return calculateTheScore((IFeed)key);
        }
    }
}
TOP

Related Classes of com.salas.bb.core.ScoresCalculator$Calculator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.