| 701 | static int estimateWINX( float sampleSum, int count, uint64_t bytesLeft ) |
| 702 | { |
| 703 | |
| 704 | if ( sampleSum > 0 && count > 0 ) |
| 705 | return (int) floor((double) bytesLeft / ((double) sampleSum / (double) count)); |
| 706 | |
| 707 | return 0; |
| 708 | } |
| 709 | |
| 710 | static int estimateGASA( uint64_t downloaded, uint64_t bytesLeft, double runningTime ) |
| 711 | { |
| 712 | double avgSpeed; |
| 713 | |
| 714 | if (runningTime > 0 && downloaded > 0) |
| 715 | { |
| 716 | avgSpeed = (double) downloaded / runningTime; |
| 717 | return (int) floor((double) bytesLeft / avgSpeed); |
| 718 | } |
| 719 | |
| 720 | return 0; |
| 721 | } |
| 722 | |
| 723 | static int estimateMAVG( int mCount, float sampleSum, float first, float last, uint64_t bytesLeft ) |
| 724 | { |
| 725 | static int mLastAvg = 0; |
| 726 | double lavg; |
| 727 | |
| 728 | if (mCount > 0) |
| 729 | { |
| 730 | if (mLastAvg == 0) |
| 731 | lavg = (int) sampleSum / mCount; |
| 732 | else |
| 733 | lavg = mLastAvg - ((double) first / (double) mCount) + ((double) last / (double) mCount); |
| 734 | |
| 735 | mLastAvg = (int) floor(lavg); |
| 736 | |
| 737 | if (lavg > 0) |
| 738 | return (int) floor((double) bytesLeft / ((lavg + (sampleSum / mCount)) / 2)); |
| 739 | |
| 740 | return 0; |
| 741 | } |
| 742 | |
| 743 | return 0; |
| 744 | } |
| 745 | |
| 746 | /** |
| 747 | * more acurate ETA |
| 748 | * shamelessly adopted from KTorrent |
| 749 | */ |
| 750 | |
| 751 | static int |
| 752 | calculateETA ( uint64_t leftUntilDone, |
| 753 | uint64_t desiredAvailable, |
| 754 | float rateDownload, |
| 755 | float perc, |
| 756 | uint64_t downloaded, |
| 757 | uint64_t bytesLeft, |
| 758 | time_t startDate ) |
| 759 | { |
| 760 | int i; |
| 761 | int eta; |
| 762 | |
| 763 | #define MSIZE 20 |
| 764 | |
| 765 | static int mStart = 0; |
| 766 | static int mEnd = -1; |
| 767 | static int mCount = 0; |
| 768 | const static int mSize = MSIZE; |
| 769 | static float mSamples[MSIZE]; |
| 770 | static double mPerc = -1; |
| 771 | |
| 772 | float sampleSum; |
| 773 | int percentage; |
| 774 | double delta; |
| 775 | double runningTime; |
| 776 | |
| 777 | if (mCount < mSize) |
| 778 | { |
| 779 | /* it's not full yet */ |
| 780 | mSamples[(++mEnd) % mSize ] = rateDownload; |
| 781 | mCount++; |
| 782 | } |
| 783 | else |
| 784 | { |
| 785 | /* since it's full I'll just replace the oldest value with new one and update all variables. */ |
| 786 | mEnd = (++mEnd) % mSize; |
| 787 | mStart = (++mStart) % mSize; |
| 788 | mSamples[mEnd] = rateDownload; |
| 789 | } |
| 790 | |
| 791 | percentage = (int)(perc) * 100; |
| 792 | |
| 793 | /* calculate percentage increasement */ |
| 794 | delta = 1 - 1 / (perc / mPerc); |
| 795 | |
| 796 | /* calculate sampleSum */ |
| 797 | for (i = 0; i < mCount; ++i) { |
| 798 | sampleSum += mSamples[i]; |
| 799 | } |
| 800 | |
| 801 | /* calculate running time */ |
| 802 | runningTime = difftime(time(NULL), startDate); |
| 803 | |
| 804 | /* remember last percentage */ |
| 805 | mPerc = perc; |
| 806 | |
| 807 | /* <100KB */ |
| 808 | if (downloaded < 1024*1024*100 && mSamples[mEnd] > 0) |
| 809 | { |
| 810 | eta = estimateGASA(downloaded, bytesLeft, runningTime); |
| 811 | return eta; |
| 812 | } |
| 813 | /* 1% of a very large torrent could be hundreds of MB so limit it to 10MB */ |
| 814 | if (percentage >= 99 && mSamples[mEnd] > 0 && bytesLeft <= 10*1024*1024*1024LL) |
| 815 | { |
| 816 | if (mCount < mSize) |
| 817 | { |
| 818 | eta = estimateWINX(sampleSum, mCount, bytesLeft); |
| 819 | |
| 820 | if (eta == 0) |
| 821 | eta = estimateGASA(downloaded, bytesLeft, runningTime); |
| 822 | |
| 823 | return eta; |
| 824 | } |
| 825 | else |
| 826 | { |
| 827 | eta = 0; |
| 828 | |
| 829 | if (delta > 0.0001) |
| 830 | eta = estimateMAVG(mCount, sampleSum, mSamples[mStart], mSamples[mEnd], bytesLeft); |
| 831 | |
| 832 | if (eta == 0) |
| 833 | eta = estimateGASA(downloaded, bytesLeft, runningTime); |
| 834 | } |
| 835 | |
| 836 | return eta; |
| 837 | } |
| 838 | |
| 839 | eta = estimateGASA(downloaded, bytesLeft, runningTime); |
| 840 | |
| 841 | return eta; |
| 842 | } |
| 843 | |