/*
* Created on May 6, 2008
* Created by Paul Gardner
*
* Copyright 2008 Vuze, Inc. All rights reserved.
*
* 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; version 2 of the License only.
*
* 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.
*/
package com.aelitis.azureus.core.metasearch;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import org.apache.commons.lang.Entities;
import org.gudy.azureus2.core3.util.DisplayFormatters;
import org.json.simple.JSONObject;
import com.aelitis.azureus.core.metasearch.utils.MomentsAgoDateFormatter;
public abstract class Result {
private static final String HTML_TAGS = "(\\<(/?[^\\>]+)\\>)" ;
private static final String DUPLICATE_SPACES = "\\s{2,}";
private Engine engine;
public abstract Date getPublishedDate();
public abstract String getCategory();
public abstract void setCategory(String category);
public abstract String getContentType();
public abstract void setContentType(String contentType);
public abstract String getName();
public abstract long getSize();
public abstract int getNbPeers();
public abstract int getNbSeeds();
public abstract int getNbSuperSeeds();
public abstract int getComments();
public abstract int getVotes();
public abstract int getVotesDown();
public abstract boolean isPrivate();
public abstract String getDRMKey();
//Links
public abstract String getDownloadLink();
public abstract String getDownloadButtonLink();
public abstract String getCDPLink();
public abstract String getPlayLink();
public abstract float getAccuracy(); // 0.0 -> 1.0 and -1 if not supported
public abstract String getSearchQuery();
public abstract String getUID();
public abstract String getHash();
protected
Result(
Engine _engine )
{
engine = _engine;
}
public Engine
getEngine()
{
return( engine );
}
public String toString() {
return getName() + " : " + getNbSeeds() + " s, " + getNbPeers() + "p, " ;
}
/*
public String getNameHTML() {
if(getName() != null) {
return( getName());
//return( XUXmlWriter.escapeXML( getName()));
//return Entities.XML.escape(getName());
}
return null;
}
public String getCategoryHTML() {
if(getCategory() != null) {
return( getCategory());
//return Entities.XML.escape(getCategory());
}
return null;
}
*/
/**
*
* @return a value between 0 and 1 representing the rank of the result
*/
public float getRank() {
int seeds = getNbSeeds();
int peers = getNbPeers();
if ( seeds < 0 ){
seeds = 0;
}
if ( peers < 0 ){
peers = 0;
}
int totalVirtualPeers = 3 * seeds + peers + 2;
int superSeeds = getNbSuperSeeds();
if(superSeeds > 0) {
totalVirtualPeers += 50 * superSeeds;
}
int votes = getVotes();
if(votes > 0) {
if(votes > 50) {
votes = 50;
}
totalVirtualPeers += 5 * votes;
}
int votesDown = getVotesDown();
if(votesDown > 0) {
totalVirtualPeers -= 200 * votesDown;
}
if(totalVirtualPeers < 2) totalVirtualPeers = 2;
float rank = (float) (Math.log(totalVirtualPeers)/Math.log(10)) / 5f;
if(rank > 2f) rank = 2f;
if(isPrivate()) {
rank /= 2;
}
String queryString = getSearchQuery();
String name = getName();
if(queryString != null && name != null) {
name = name.toLowerCase( Locale.ENGLISH );
String token = "";
List<String> tokens = new ArrayList<String>();
char[] chars = queryString.toCharArray();
for ( char c: chars ){
if ( Character.isLetterOrDigit( c )){
token += String.valueOf(c).toLowerCase( Locale.ENGLISH );
}else{
if ( token.length() > 0 ){
tokens.add( token );
token = "";
}
}
}
if ( token.length() > 0 ){
tokens.add( token );
}
for ( String s: tokens ){
if( !name.contains( s )){
rank /= 2;
}
}
}
rank = applyRankBias( rank );
return rank;
}
protected float
applyRankBias(
float _rank )
{
float rank = engine.applyRankBias( _rank );
/*
if ( rank != _rank ){
System.out.println( "bias applied for " + engine.getName() + ": " + _rank + "-> " + rank );
}
*/
return( rank );
}
public Map toJSONMap() {
Map object = new JSONObject();
try {
object.put("d", MomentsAgoDateFormatter.getMomentsAgoString(this.getPublishedDate()));
object.put("ts", "" + this.getPublishedDate().getTime());
} catch(Exception e) {
object.put("d", "unknown");
object.put("ts", "0");
}
object.put("c", this.getCategory());
object.put("n",this.getName());
int super_seeds = getNbSuperSeeds();
int seeds = getNbSeeds();
int seed_total = -1;
if ( super_seeds > 0 ){
seed_total = 10*super_seeds + new Random().nextInt(10);
}
if ( seeds > 0 ){
if ( seed_total == -1 ){
seed_total = 0;
}
seed_total += seeds;
}
object.put("s","" + seed_total);
if(this.getNbPeers() >= 0) {
object.put("p","" + this.getNbPeers());
} else {
object.put("p","-1");
}
int comments = getComments();
if ( comments >= 0 ){
object.put( "co", "" + comments );
}
long size = this.getSize();
if(size >= 0) {
// max three digits for display purposes
String size_str = DisplayFormatters.formatByteCountToKiBEtc( size );
size_str = DisplayFormatters.trimDigits( size_str, 3 );
object.put("l", size_str );
object.put("lb", "" + size );
} else {
object.put("l", "-1");
object.put("lb", "0");
}
object.put("r", "" + this.getRank());
object.put("ct", this.getContentType());
float accuracy = getAccuracy();
if ( accuracy >= 0 ){
if ( accuracy > 1 ){
accuracy = 1;
}
object.put ("ac", "" + accuracy );
}
if ( this.getCDPLink().length() > 0 ){
object.put("cdp", this.getCDPLink());
}
// This is also used by subscription code to extract download link so if you
// change this you'll need to change that too...
if ( this.getDownloadLink().length() > 0 ){
object.put("dl", this.getDownloadLink());
}
if ( this.getDownloadButtonLink().length() > 0 ){
object.put("dbl", this.getDownloadButtonLink());
}
if ( this.getPlayLink().length() > 0 ){
object.put("pl", this.getPlayLink());
}
if ( this.getVotes() >= 0 ){
object.put("v", "" + this.getVotes());
}
if ( this.getVotesDown() >= 0 ){
object.put("vd", "" + this.getVotesDown());
}
String drmKey = getDRMKey();
if(drmKey != null) {
object.put("dk",drmKey);
}
// used by subscriptions...
String uid = getUID();
if ( uid != null ){
object.put( "u", uid );
}
object.put("pr", this.isPrivate() ? "1" : "0");
String hash = getHash();
if ( hash != null ){
object.put( "h", hash );
}
return object;
}
public static void
adjustRelativeTerms(
Map map )
{
String ts = (String)map.get( "ts" );
if ( ts != null ){
long l_ts = Long.parseLong(ts);
if ( l_ts > 0 ){
map.put("d", MomentsAgoDateFormatter.getMomentsAgoString(new Date( l_ts )));
}
}
}
protected static final String removeHTMLTags(String input) {
if ( input == null ){
return( null );
}
String result = input.replaceAll(HTML_TAGS, " ");
return result.replaceAll(DUPLICATE_SPACES, " ").trim();
}
protected static final String unescapeEntities( String input )
{
if ( input == null ){
return( null );
}
return( Entities.HTML40.unescape( input ));
}
}