美文网首页
2018-11-26

2018-11-26

作者: ye_evan_ye | 来源:发表于2018-11-26 16:06 被阅读5次

/*

* Copyright 2018 ARP Network

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*      http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.arpnetwork.arpdevice.ui.miner;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Looper;

import android.support.v4.content.LocalBroadcastManager;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.AdapterView;

import android.widget.ListView;

import org.arpnetwork.arpdevice.R;

import org.arpnetwork.arpdevice.app.AtomicNonce;

import org.arpnetwork.arpdevice.constant.Constant;

import org.arpnetwork.arpdevice.contracts.tasks.AbsExceptionTask;

import org.arpnetwork.arpdevice.contracts.tasks.OnValueResult;

import org.arpnetwork.arpdevice.contracts.tasks.SimpleOnValueResult;

import org.arpnetwork.arpdevice.dialog.PromiseDialog;

import org.arpnetwork.arpdevice.rpc.RPCRequest;

import org.arpnetwork.arpdevice.ui.base.BaseFragment;

import org.arpnetwork.arpdevice.ui.bean.Miner;

import org.arpnetwork.arpdevice.ui.bean.MinerInfo;

import org.arpnetwork.arpdevice.ui.order.details.ExchangeActivity;

import org.arpnetwork.arpdevice.ui.widget.EmptyView;

import org.arpnetwork.arpdevice.util.OKHttpUtils;

import org.arpnetwork.arpdevice.util.SimpleCallback;

import org.arpnetwork.arpdevice.util.UIHelper;

import java.math.BigInteger;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import okhttp3.Request;

import okhttp3.Response;

import static org.arpnetwork.arpdevice.config.Config.API_SERVER_INFO;

import static org.arpnetwork.arpdevice.constant.Constant.KEY_EXCHANGE_AMOUNT;

import static org.arpnetwork.arpdevice.constant.Constant.KEY_EXCHANGE_TYPE;

import static org.arpnetwork.arpdevice.ui.miner.BindMinerIntentService.OPERATION_CASH;

public class MinerListFragment extends BaseFragment {

    private static final int PING_INTERVAL = 1000;

    private static final int PING_COUNT = 3;

    private static final int UNREACHABLE_TIME_MS = 60 * 1000;

    private Map<Integer, List<Integer>> mPings = new HashMap<Integer, List<Integer>>();

    private Thread mPingThread;

    private Miner mBoundMiner;

    private ListView mMinerList;

    private MinerAdapter mAdapter;

    private ListLoadTask mListLoader;

    private OKHttpUtils mOkHttpUtils;

    private BindStateReceiver mBindStateReceiver;

    private boolean mIgnoreExchage;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setTitle(R.string.miner_list);

        if (getArguments() != null) {

            mBoundMiner = (Miner) getArguments().getSerializable(Constant.KEY_MINER);

        }

        mOkHttpUtils = new OKHttpUtils();

        registerReceiver();

    }

    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_miner_list, container, false);

    }

    @Override

    public void onViewCreated(View view, Bundle savedInstanceState) {

        initViews();

        startLoad();

    }

    @Override

    public void onDestroy() {

        super.onDestroy();

        if (mPingThread != null) {

            mPingThread.interrupt();

            mPingThread = null;

        }

        mOkHttpUtils.cancelTag(API_SERVER_INFO);

        cancelPotentialTask();

        if (mBindStateReceiver != null) {

            LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mBindStateReceiver);

            mBindStateReceiver = null;

        }

    }

    @Override

    protected void loadData() {

        cancelPotentialTask();

        mListLoader = new ListLoadTask(new SimpleOnValueResult<List<Miner>>() {

            @Override

            public void onValueResult(List<Miner> result) {

                if (result != null && result.size() > 0) {

                    showContentView();

                    for (int i = 0; i < result.size(); i++) {

                        Miner miner = result.get(i);

                        String url = "http://" + miner.getIpString() + ":" + miner.getPortHttpInt();

                        loadMinerLoadInfo(i, url, miner.getAddress());

                    }

                    loadMinerPingAsync(result);

                    mAdapter.setData(result);

                    if (mBoundMiner != null) {

                        TaskInfo task = StateHolder.getTaskByState(StateHolder.STATE_BIND_RUNNING);

                        if (task != null) {

                            mAdapter.updateBindState(mBoundMiner.getAddress(), StateHolder.STATE_UNBIND_RUNNING);

                            mAdapter.updateBindState(task.address, StateHolder.STATE_BIND_RUNNING);

                        } else {

                            mAdapter.updateBindState(mBoundMiner.getAddress(), StateHolder.STATE_BIND_SUCCESS);

                        }

                    }

                    if (StateHolder.getTaskByState(StateHolder.STATE_BIND_RUNNING) != null) {

                        TaskInfo task = StateHolder.getTaskByState(StateHolder.STATE_BIND_RUNNING);

                        mAdapter.updateBindState(task.address, StateHolder.STATE_BIND_RUNNING);

                    } else if (StateHolder.getTaskByState(StateHolder.STATE_UNBIND_RUNNING) != null) {

                        TaskInfo task = StateHolder.getTaskByState(StateHolder.STATE_UNBIND_RUNNING);

                        mAdapter.updateBindState(task.address, StateHolder.STATE_UNBIND_RUNNING);

                    }

                } else {

                    showEmptyView(EmptyView.STATE_EMPTY);

                }

            }

            @Override

            public void onFail(Throwable throwable) {

                showEmptyView(EmptyView.STATE_FAIL);

            }

        });

        mListLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

    }

    @Override

    protected View getContentView() {

        return mMinerList;

    }

    private void cancelPotentialTask() {

        if (mListLoader != null) {

            mListLoader.cancel(true);

            mListLoader = null;

        }

    }

    private void registerReceiver() {

        IntentFilter statusIntentFilter = new IntentFilter(Constant.BROADCAST_ACTION_STATUS);

        statusIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);

        mBindStateReceiver = new BindStateReceiver();

        LocalBroadcastManager.getInstance(getActivity())

                .registerReceiver(mBindStateReceiver, statusIntentFilter);

    }

    private void initViews() {

        mAdapter = new MinerAdapter(getContext());

        mMinerList = (ListView) findViewById(R.id.iv_miners);

        mMinerList.setAdapter(mAdapter);

        mMinerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override

            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                Miner miner = mAdapter.getItem(position);

                if (mBoundMiner != null && mBoundMiner.getAddress().equals(miner.getAddress())) {

                    showMinerPage(miner);

                    return;

                }

                TaskInfo bindingTask = StateHolder.getTaskByState(StateHolder.STATE_BIND_RUNNING);

                TaskInfo unbindingTask = StateHolder.getTaskByState(StateHolder.STATE_UNBIND_RUNNING);

                if (bindingTask != null && !miner.getAddress().equals(bindingTask.address)) {

                    UIHelper.showToast(getActivity(), R.string.binding_other);

                } else if (unbindingTask != null && !miner.getAddress().equals(unbindingTask.address)) {

                    UIHelper.showToast(getActivity(), R.string.unbinding_other);

                } else {

                    if (mIgnoreExchage) {

                        showMinerPage(miner);

                    } else {

                        checkPromise(miner);

                    }

                }

            }

        });

    }

    private void checkPromise(final Miner miner) {

        PromiseDialog.show(getContext(), R.string.exchange_change_miner_msg, getString(R.string.exchange_change_miner_ignore),

                new PromiseDialog.PromiseListener() {

                    @Override

                    public void onError() {

                        if (getActivity() == null) return;

                        finish();

                    }

                    @Override

                    public void onExchange(BigInteger unexchanged) {

                        if (getActivity() == null) return;

                        Bundle bundle = new Bundle();

                        bundle.putInt(KEY_EXCHANGE_TYPE, OPERATION_CASH);

                        bundle.putString(KEY_EXCHANGE_AMOUNT, unexchanged.toString());

                        bundle.putSerializable(Constant.KEY_MINER, miner);

                        startActivity(ExchangeActivity.class, bundle);

                    }

                    @Override

                    public void onIgnore() {

                        if (getActivity() == null) return;

                        showMinerPage(miner);

                        mIgnoreExchage = true;

                    }

                });

    }

    private void showMinerPage(Miner miner) {

        Bundle bundle = new Bundle();

        bundle.putSerializable(Constant.KEY_MINER, miner);

        startActivity(BindMinerActivity.class, bundle);

    }

    private void startLoad() {

        loadData();

    }

    private void loadMinerLoadInfo(final int index, final String url, String minerAddr) {

        String nonce = AtomicNonce.getAndIncrement(minerAddr);

        RPCRequest request = new RPCRequest();

        request.setId(nonce);

        request.setMethod(API_SERVER_INFO);

        mOkHttpUtils.post(url, request.toJSON(), API_SERVER_INFO, new SimpleCallback<MinerInfo>() {

            @Override

            public void onFailure(Request request, Exception e) {

            }

            @Override

            public void onSuccess(Response response, MinerInfo result) {

                mAdapter.updateLoad(index, result);

            }

            @Override

            public void onError(Response response, int code, Exception e) {

            }

        });

    }

    private void loadMinerPingAsync(final List<Miner> miners) {

        mPingThread = new Thread(new Runnable() {

            @Override

            public void run() {

                try {

                    loadMinerPing(miners);

                } catch (InterruptedException ignored) {

                    Log.e("evan", "loadMinerPingAsync InterruptedException");

                }

            }

        });

        mPingThread.start();

    }

    private void loadMinerPing(List<Miner> miners) throws InterruptedException {

        for (int i = 0; i < miners.size(); i++) {

            Miner miner = miners.get(i);

            String url = "http://" + miner.getIpString() + ":" + miner.getPortHttpInt();

            for (int j = 0; j < PING_COUNT; j++) {

                Thread.sleep(PING_INTERVAL);

                loadPingInternal(i, url, miner.getAddress());

            }

        }

    }

    private void loadPingInternal(final int index, final String url, String minerAddr) {

        String nonce = AtomicNonce.getAndIncrement(minerAddr);

        RPCRequest request = new RPCRequest();

        request.setId(nonce);

        request.setMethod(API_SERVER_INFO);

        final long start = System.currentTimeMillis();

        Log.e("evan", "url = " + url);

        mOkHttpUtils.post(url, request.toJSON(), API_SERVER_INFO, new SimpleCallback<MinerInfo>() {

            @Override

            public void onFailure(Request request, Exception e) {

                pingReachable(index, start, false);

            }

            @Override

            public void onSuccess(Response response, MinerInfo result) {

                pingReachable(index, start, true);

            }

            @Override

            public void onError(Response response, int code, Exception e) {

                pingReachable(index, start, true);

            }

        });

    }

    private void pingReachable(int index, long start, boolean reachable) {

        Log.e("evan", "pingReachable Main = " + (Looper.myLooper() == Looper.getMainLooper())+" index = "+index);

        if (mPings.containsKey(index)) {

            Log.e("evan", "pingReachable containsKey index = " + index + " mPings.size = " + mPings.size());

            List<Integer> list = mPings.get(index);

            if (reachable) {

                list.add((int) (System.currentTimeMillis() - start) / 2);

            } else {

                list.add(UNREACHABLE_TIME_MS);

            }

            Log.e("evan", "pingReachable index = " + index + " list.size = " + list.size());

            if (list.size() == PING_COUNT) {

                for (Iterator<Map.Entry<Integer, List<Integer>>> it = mPings.entrySet().iterator(); it.hasNext(); ) {

                    Map.Entry<Integer, List<Integer>> item = it.next();

                    if (item.getKey() == index) {

                        int total = 0;

                        int unreachableCount = 0;

                        List<Integer> pings = item.getValue();

                        for (int i = 0; i < pings.size(); i++) {

                            Log.e("evan", "test");

                        }

                        for (int i = 0; i < pings.size(); i++) {

                            int ping = pings.get(i);

//                            Log.e("evan", "item ping = " + pings.get(i));

                            Log.e("evan", "item ping = " + ping);

                            if (ping == UNREACHABLE_TIME_MS) {

                                unreachableCount += 1;

                            }

                            total += ping;

                        }

                        /*for (Integer ping : pings) {

                            if (ping == UNREACHABLE_TIME_MS) {

                                unreachableCount += 1;

                            }

                            total += ping;

                            Log.e("evan","item ping = "+ping);

                        }*/

                        Log.e("evan", "unreachableCount = " + unreachableCount + " pings.size() = " + pings.size());

                        int avg;

                        if (unreachableCount == pings.size()) {

                            avg = -1;

                            Log.e("evan", "avg = -1");

                        } else {

                            avg = total / pings.size();

                            Log.e("evan", "avg = " + avg);

                        }

                        mAdapter.updatePing(index, avg);

//                        it.remove();

                        break;

                    }

                }

            }

        } else {

            Log.e("evan", "pingReachable not containsKey index = " + index + " mPings.size = " + mPings.size());

            List<Integer> list = new ArrayList<>();

//            ConcurrentLinkedQueue<Integer> list = new ConcurrentLinkedQueue<>();

            if (reachable) {

                list.add((int) (System.currentTimeMillis() - start) / 2);

            } else {

                list.add(UNREACHABLE_TIME_MS);

            }

            mPings.put(index, list);

        }

    }

    private class BindStateReceiver extends BroadcastReceiver {

        @Override

        public void onReceive(Context context, Intent intent) {

            switch (intent.getIntExtra(Constant.EXTENDED_DATA_STATUS, StateHolder.STATE_APPROVE_RUNNING)) {

                case StateHolder.STATE_BIND_RUNNING:

                    if (mBoundMiner != null && mBoundMiner.getAddress() != null) {

                        mAdapter.updateBindState(mBoundMiner.getAddress(), StateHolder.STATE_UNBIND_RUNNING);

                    }

                    TaskInfo task = StateHolder.getTaskByState(StateHolder.STATE_BIND_RUNNING);

                    mAdapter.updateBindState(task.address, StateHolder.STATE_BIND_RUNNING);

                    break;

                case StateHolder.STATE_BIND_SUCCESS:

                    UIHelper.showToast(getActivity(), getString(R.string.bind_success));

                    if (mBoundMiner != null) {

                        mAdapter.removeState(mBoundMiner.getAddress());

                    }

                    TaskInfo taskSuccess = StateHolder.getTaskByState(StateHolder.STATE_BIND_SUCCESS);

                    mAdapter.updateBindState(taskSuccess.address, StateHolder.STATE_BIND_SUCCESS);

                    mBoundMiner = new Miner();

                    mBoundMiner.setAddress(taskSuccess.address);

                    break;

                case StateHolder.STATE_BIND_FAILED:

                    UIHelper.showToast(getActivity(), getString(R.string.bind_failed));

                    TaskInfo taskFailed = StateHolder.getTaskByState(StateHolder.STATE_BIND_FAILED);

                    mAdapter.updateBindState(taskFailed.address, StateHolder.STATE_BIND_FAILED);

                    break;

                case StateHolder.STATE_UNBIND_RUNNING:

                    TaskInfo unbindTask = StateHolder.getTaskByState(StateHolder.STATE_UNBIND_RUNNING);

                    mAdapter.updateBindState(unbindTask.address, StateHolder.STATE_UNBIND_RUNNING);

                    break;

                case StateHolder.STATE_UNBIND_SUCCESS:

                    UIHelper.showToast(getActivity(), getString(R.string.unbind_success));

                    mBoundMiner = null;

                    finish();

                    break;

                case StateHolder.STATE_UNBIND_FAILED:

                    TaskInfo unbindFailed = StateHolder.getTaskByState(StateHolder.STATE_UNBIND_FAILED);

                    mAdapter.updateBindState(unbindFailed.address, StateHolder.STATE_UNBIND_FAILED);

                    break;

                default:

                    break;

            }

        }

    }

    private static class ListLoadTask extends AbsExceptionTask<Void, Void, List<Miner>> {

        public ListLoadTask(OnValueResult<List<Miner>> onValueResult) {

            super(onValueResult);

        }

        @Override

        public List<Miner> onInBackground(Void... voids) throws Exception {

            return BindMinerHelper.getMinerList();

        }

    }

}

相关文章

网友评论

      本文标题:2018-11-26

      本文链接:https://www.haomeiwen.com/subject/cyvbqqtx.html