问:
Android RecyclerView Changes text to Image when scroll
Can anyone please help me out here???

Problem statement: I am making a chat application that is almost ready in ChatActivity. Functionality is the user can send images and text together but while sending text it's fine. The problem starts when I am sending images. And after sending when I scroll up to my all the texts start to change into the recently sent image.

ChatActivity.xml -

```<code><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/bg_light"
    tools:context=".ChatActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/backArrow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_back_arrow"
                app:tint="@color/white" />

            <de.hdodenhof.circleimageview.CircleImageView
                android:id="@+id/profile_image"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_marginStart="5dp"
                android:padding="5dp"
                android:src="@drawable/avatar"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toEndOf="@+id/backArrow"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/userName"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginTop="3dp"
                android:layout_marginEnd="16dp"
                android:layout_marginBottom="13dp"
                android:fontFamily="@font/roboto"
                android:text=""
                android:textColor="@color/white"
                android:textSize="20sp"
                android:textStyle="bold"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/imageView7"
                app:layout_constraintStart_toEndOf="@+id/profile_image"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/lastSeen"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginEnd="16dp"
                android:layout_marginBottom="2dp"
                android:fontFamily="@font/roboto_light"
                android:text=""
                android:textColor="@color/white"
                android:textSize="12sp"
                android:textStyle="bold"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/imageView7"
                app:layout_constraintStart_toEndOf="@+id/profile_image"
                app:layout_constraintTop_toBottomOf="@+id/userName" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_begin="-22dp" />

            <androidx.constraintlayout.widget.Barrier
                android:id="@+id/barrier2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:barrierDirection="left"
                tools:layout_editor_absoluteX="395dp" />

            <ImageView
                android:id="@+id/imageView7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="10dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_more"
                app:tint="@color/white" />

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.appcompat.widget.Toolbar>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/chatRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="611dp"
        android:nestedScrollingEnabled="false">

    </androidx.recyclerview.widget.RecyclerView>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="4dp">

        <View
            android:id="@+id/view14"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:background="@drawable/follow_active_btn"
            app:layout_constraintBottom_toBottomOf="@+id/etMessage"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/etMessage" />

        <EditText
            android:id="@+id/etMessage"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginBottom="4dp"
            android:background="@color/transparent"
            android:ems="10"
            android:hint="Message"
            android:inputType="textMultiLine"
            android:maxLines="4"
            android:minHeight="48dp"
            android:paddingStart="4dp"
            android:paddingLeft="4dp"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/sendMessageImage"
            app:layout_constraintStart_toStartOf="parent" />

        <ImageView
            android:id="@+id/sendMessage"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:layout_marginEnd="8dp"
            android:padding="4dp"
            app:layout_constraintBottom_toBottomOf="@+id/etMessage"
            app:layout_constraintEnd_toEndOf="@+id/view14"
            app:layout_constraintTop_toTopOf="@+id/etMessage"
            app:srcCompat="@drawable/comment"
            app:tint="@color/purple_500" />

        <ImageView
            android:id="@+id/sendMessageImage"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:padding="4dp"
            app:layout_constraintBottom_toBottomOf="@+id/sendMessage"
            app:layout_constraintEnd_toStartOf="@+id/sendMessage"
            app:layout_constraintTop_toTopOf="@+id/sendMessage"
            app:srcCompat="@drawable/clip"
            app:tint="@color/black" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>
</code>```

ChatAdapter.java -

```<code>package com.codinggeekers.lmsbeta.Adapter;

import android.content.Context;
import android.media.Image;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.codinggeekers.lmsbeta.Models.MessageModel;
import com.codinggeekers.lmsbeta.R;
import com.google.firebase.auth.FirebaseAuth;
import com.squareup.picasso.Picasso;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

public class ChatAdapter extends RecyclerView.Adapter {

    ArrayList<MessageModel> list;
    Context context;

    int SENDER_VIEW_TYPE = 1;
    int RECEIVER_VIEW_TYPE = 2;

    public ChatAdapter(ArrayList<MessageModel> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if(viewType == SENDER_VIEW_TYPE) {
            View view = LayoutInflater.from(context).inflate(R.layout.sample_sender, parent, false);
            return new SenderViewHolder(view);
        }
        else {
            View view = LayoutInflater.from(context).inflate(R.layout.sample_receiver, parent, false);
            return new ReceiverViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        MessageModel message = list.get(position);

        Timestamp ts = new Timestamp(message.getTimestamp());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm a");
        String time = simpleDateFormat.format(ts.getTime());

        RequestOptions requestOptions = new RequestOptions();
        requestOptions = requestOptions.transforms(new CenterCrop(), new RoundedCorners(10));

        if(holder.getClass() == SenderViewHolder.class) {
            if (message.getMsgImg()!=null) {
                ((SenderViewHolder)holder).senderImageLayout.setVisibility(View.VISIBLE);
                ((SenderViewHolder)holder).senderTextLayout.setVisibility(View.GONE);
//                Picasso.get().load(message.getMsgImg()).placeholder(R.drawable.placeholder).into(((SenderViewHolder)holder).senderImage);
                Glide.with(((SenderViewHolder)holder).itemView.getContext()).load(message.getMsgImg()).apply(requestOptions)
                        .placeholder(R.drawable.placeholder).into(((SenderViewHolder)holder).senderImage);
            } else {
                ((SenderViewHolder)holder).senderMsg.setText(message.getMessage());
                ((SenderViewHolder)holder).senderTime.setText(time);
            }
        }
        else {
            if (message.getMsgImg()!=null) {
                ((ReceiverViewHolder)holder).receiverImageLayout.setVisibility(View.VISIBLE);
//                Picasso.get().load(message.getMsgImg()).placeholder(R.drawable.placeholder).into(((ReceiverViewHolder)holder).receiverImage);
                Glide.with(((ReceiverViewHolder)holder).itemView.getContext()).load(message.getMsgImg()).apply(requestOptions)
                        .placeholder(R.drawable.placeholder).into(((ReceiverViewHolder)holder).receiverImage);
            } else {
                ((ReceiverViewHolder)holder).receiverMsg.setText(message.getMessage());
                ((ReceiverViewHolder)holder).receiverTime.setText(time);
            }
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(list.get(position).getuId().equals(FirebaseAuth.getInstance().getUid())) {
            return SENDER_VIEW_TYPE;
        }
        else {
            return RECEIVER_VIEW_TYPE;
        }
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    public class ReceiverViewHolder extends RecyclerView.ViewHolder {

        TextView receiverMsg, receiverTime;
        ImageView receiverImage;
        ConstraintLayout receiverImageLayout;

        public ReceiverViewHolder(@NonNull View itemView) {
            super(itemView);

            receiverMsg = itemView.findViewById(R.id.receiverText);
            receiverTime = itemView.findViewById(R.id.receiverTime);
            receiverImage = itemView.findViewById(R.id.receiverImage);
            receiverImageLayout = itemView.findViewById(R.id.imageConstraintLayoutReceiver);
        }
    }

    public class SenderViewHolder extends RecyclerView.ViewHolder {

        TextView senderMsg, senderTime;
        ImageView senderImage;
        ConstraintLayout senderImageLayout;
        ConstraintLayout senderTextLayout;

        public SenderViewHolder(@NonNull View itemView) {
            super(itemView);

            senderMsg = itemView.findViewById(R.id.senderText);
            senderTime = itemView.findViewById(R.id.senderTime);
            senderImage = itemView.findViewById(R.id.senderImage);
            senderImageLayout = itemView.findViewById(R.id.imageConstraintLayoutSender);
            senderTextLayout = itemView.findViewById(R.id.textConstraintLayoutSender);
        }
    }
}
</code>```

ChatActivity.java -

```<code>package com.codinggeekers.lmsbeta;

import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

import com.codinggeekers.lmsbeta.Adapter.ChatAdapter;
import com.codinggeekers.lmsbeta.Models.MessageModel;

import com.codinggeekers.lmsbeta.databinding.ActivityChatBinding;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.Date;

public class ChatActivity extends AppCompatActivity {

    ActivityChatBinding binding;

    ProgressDialog dialog;

    FirebaseAuth auth;
    FirebaseDatabase database;
    FirebaseStorage storage;

    ActivityResultLauncher<String> galleryLauncher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityChatBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        auth = FirebaseAuth.getInstance();
        database = FirebaseDatabase.getInstance();
        storage = FirebaseStorage.getInstance();

        dialog = new ProgressDialog(this);

        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setTitle("Sending Image...");
        dialog.setMessage("Please wait...");
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);

        // Sender and Receiver Ids
        final String senderId = auth.getUid();
        String receiveId = getIntent().getStringExtra("userId");
        String userName = getIntent().getStringExtra("userName");
        String profilePic = getIntent().getStringExtra("profilePic");

        binding.userName.setText(userName);
        Picasso.get().load(profilePic).placeholder(R.drawable.avatar).into(binding.profileImage);

        binding.backArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(ChatActivity.this, UsersChatActivity.class);
                startActivity(intent);
            }
        });

        final ArrayList<MessageModel> messageModels = new ArrayList<MessageModel>();

        final ChatAdapter chatAdapter = new ChatAdapter(messageModels, this);
        binding.chatRecyclerView.setAdapter(chatAdapter);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setStackFromEnd(true);
        binding.chatRecyclerView.setHasFixedSize(true);
        binding.chatRecyclerView.setLayoutManager(layoutManager);

        final String senderRoom = senderId + receiveId;
        final String receiverRoom = receiveId + senderId;

        database.getReference().child("Chats")
                .child(senderRoom)
                .addValueEventListener(new ValueEventListener() {
                    @SuppressLint("NotifyDataSetChanged")
                    @Override
                    public void onDataChange(@NonNull DataSnapshot snapshot) {
                        messageModels.clear();
                        for (DataSnapshot snapshot1 : snapshot.getChildren()) {
                            MessageModel model = snapshot1.getValue(MessageModel.class);
                            messageModels.add(model);
                        }
                        chatAdapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError error) {

                    }
                });

        binding.sendMessage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String message = binding.etMessage.getText().toString();
                if (message.matches("")) {

                } else {
                    final MessageModel model = new MessageModel(senderId, message, "text");
                    model.setTimestamp(new Date().getTime());
                    binding.etMessage.setText("");
                    database.getReference().child("Chats")
                            .child(senderRoom)
                            .push()
                            .setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(@NonNull Void unused) {
                            database.getReference().child("Chats").child(receiverRoom).push().setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                                @Override
                                public void onSuccess(@NonNull Void unused) {

                                }
                            });
                        }
                    });
                }
            }
        });

        binding.sendMessageImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                galleryLauncher.launch("image/*");
            }
        });

        galleryLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), new ActivityResultCallback<Uri>() {
            @Override
            public void onActivityResult(Uri result) {
                dialog.show();
                final StorageReference reference = storage.getReference().child("chats")
                        .child(senderRoom).child(new Date().getTime() + "");
                reference.putFile(result).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        reference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(Uri uri) {
                                final MessageModel model = new MessageModel(senderId, new Date().getTime(), uri.toString(), "image");
                                database.getReference()
                                        .child("Chats")
                                        .child(senderRoom)
                                        .push()
                                        .setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                                    @Override
                                    public void onSuccess(Void unused) {
                                        database.getReference().child("Chats").child(receiverRoom).push().setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                                            @Override
                                            public void onSuccess(Void unused) {
                                                dialog.dismiss();
                                                binding.sendMessageImage.setImageURI(Uri.EMPTY);
                                                Intent intent = getIntent();
                                                finish();
                                                startActivity(intent);
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                });
            }
        });

        binding.userName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(ChatActivity.this, FriendsProfileActivity.class);
                intent.putExtra("userName", userName);
                intent.putExtra("userId", receiveId);
                intent.putExtra("profilePic", profilePic);
                startActivity(intent);
            }
        });

    }
}
</code>```

答:
ItemViewType should start at 0.

Try to change them to this:

```<code>    int SENDER_VIEW_TYPE = 0;
    int RECEIVER_VIEW_TYPE = 1;
</code>```

Body:
Can anyone please help me out here???

Problem statement: I am making a chat application that is almost ready in ChatActivity. Functionality is the user can send images and text together but while sending text it's fine. The problem starts when I am sending images. And after sending when I scroll up to my all the texts start to change into the recently sent image.

ChatActivity.xml -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/bg_light"
    tools:context=".ChatActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/backArrow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_back_arrow"
                app:tint="@color/white" />

            <de.hdodenhof.circleimageview.CircleImageView
                android:id="@+id/profile_image"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_marginStart="5dp"
                android:padding="5dp"
                android:src="@drawable/avatar"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toEndOf="@+id/backArrow"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/userName"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginTop="3dp"
                android:layout_marginEnd="16dp"
                android:layout_marginBottom="13dp"
                android:fontFamily="@font/roboto"
                android:text=""
                android:textColor="@color/white"
                android:textSize="20sp"
                android:textStyle="bold"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/imageView7"
                app:layout_constraintStart_toEndOf="@+id/profile_image"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/lastSeen"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginEnd="16dp"
                android:layout_marginBottom="2dp"
                android:fontFamily="@font/roboto_light"
                android:text=""
                android:textColor="@color/white"
                android:textSize="12sp"
                android:textStyle="bold"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/imageView7"
                app:layout_constraintStart_toEndOf="@+id/profile_image"
                app:layout_constraintTop_toBottomOf="@+id/userName" />

            <androidx.constraintlayout.widget.Guideline
                android:id="@+id/guideline2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_constraintGuide_begin="-22dp" />

            <androidx.constraintlayout.widget.Barrier
                android:id="@+id/barrier2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:barrierDirection="left"
                tools:layout_editor_absoluteX="395dp" />

            <ImageView
                android:id="@+id/imageView7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="10dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_more"
                app:tint="@color/white" />

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.appcompat.widget.Toolbar>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/chatRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="611dp"
        android:nestedScrollingEnabled="false">

    </androidx.recyclerview.widget.RecyclerView>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="4dp">

        <View
            android:id="@+id/view14"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:background="@drawable/follow_active_btn"
            app:layout_constraintBottom_toBottomOf="@+id/etMessage"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/etMessage" />

        <EditText
            android:id="@+id/etMessage"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginBottom="4dp"
            android:background="@color/transparent"
            android:ems="10"
            android:hint="Message"
            android:inputType="textMultiLine"
            android:maxLines="4"
            android:minHeight="48dp"
            android:paddingStart="4dp"
            android:paddingLeft="4dp"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/sendMessageImage"
            app:layout_constraintStart_toStartOf="parent" />

        <ImageView
            android:id="@+id/sendMessage"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:layout_marginEnd="8dp"
            android:padding="4dp"
            app:layout_constraintBottom_toBottomOf="@+id/etMessage"
            app:layout_constraintEnd_toEndOf="@+id/view14"
            app:layout_constraintTop_toTopOf="@+id/etMessage"
            app:srcCompat="@drawable/comment"
            app:tint="@color/purple_500" />

        <ImageView
            android:id="@+id/sendMessageImage"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:padding="4dp"
            app:layout_constraintBottom_toBottomOf="@+id/sendMessage"
            app:layout_constraintEnd_toStartOf="@+id/sendMessage"
            app:layout_constraintTop_toTopOf="@+id/sendMessage"
            app:srcCompat="@drawable/clip"
            app:tint="@color/black" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>

ChatAdapter.java -

package com.codinggeekers.lmsbeta.Adapter;

import android.content.Context;
import android.media.Image;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.codinggeekers.lmsbeta.Models.MessageModel;
import com.codinggeekers.lmsbeta.R;
import com.google.firebase.auth.FirebaseAuth;
import com.squareup.picasso.Picasso;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

public class ChatAdapter extends RecyclerView.Adapter {

    ArrayList<MessageModel> list;
    Context context;

    int SENDER_VIEW_TYPE = 1;
    int RECEIVER_VIEW_TYPE = 2;

    public ChatAdapter(ArrayList<MessageModel> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if(viewType == SENDER_VIEW_TYPE) {
            View view = LayoutInflater.from(context).inflate(R.layout.sample_sender, parent, false);
            return new SenderViewHolder(view);
        }
        else {
            View view = LayoutInflater.from(context).inflate(R.layout.sample_receiver, parent, false);
            return new ReceiverViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        MessageModel message = list.get(position);

        Timestamp ts = new Timestamp(message.getTimestamp());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm a");
        String time = simpleDateFormat.format(ts.getTime());

        RequestOptions requestOptions = new RequestOptions();
        requestOptions = requestOptions.transforms(new CenterCrop(), new RoundedCorners(10));

        if(holder.getClass() == SenderViewHolder.class) {
            if (message.getMsgImg()!=null) {
                ((SenderViewHolder)holder).senderImageLayout.setVisibility(View.VISIBLE);
                ((SenderViewHolder)holder).senderTextLayout.setVisibility(View.GONE);
//                Picasso.get().load(message.getMsgImg()).placeholder(R.drawable.placeholder).into(((SenderViewHolder)holder).senderImage);
                Glide.with(((SenderViewHolder)holder).itemView.getContext()).load(message.getMsgImg()).apply(requestOptions)
                        .placeholder(R.drawable.placeholder).into(((SenderViewHolder)holder).senderImage);
            } else {
                ((SenderViewHolder)holder).senderMsg.setText(message.getMessage());
                ((SenderViewHolder)holder).senderTime.setText(time);
            }
        }
        else {
            if (message.getMsgImg()!=null) {
                ((ReceiverViewHolder)holder).receiverImageLayout.setVisibility(View.VISIBLE);
//                Picasso.get().load(message.getMsgImg()).placeholder(R.drawable.placeholder).into(((ReceiverViewHolder)holder).receiverImage);
                Glide.with(((ReceiverViewHolder)holder).itemView.getContext()).load(message.getMsgImg()).apply(requestOptions)
                        .placeholder(R.drawable.placeholder).into(((ReceiverViewHolder)holder).receiverImage);
            } else {
                ((ReceiverViewHolder)holder).receiverMsg.setText(message.getMessage());
                ((ReceiverViewHolder)holder).receiverTime.setText(time);
            }
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(list.get(position).getuId().equals(FirebaseAuth.getInstance().getUid())) {
            return SENDER_VIEW_TYPE;
        }
        else {
            return RECEIVER_VIEW_TYPE;
        }
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    public class ReceiverViewHolder extends RecyclerView.ViewHolder {

        TextView receiverMsg, receiverTime;
        ImageView receiverImage;
        ConstraintLayout receiverImageLayout;

        public ReceiverViewHolder(@NonNull View itemView) {
            super(itemView);

            receiverMsg = itemView.findViewById(R.id.receiverText);
            receiverTime = itemView.findViewById(R.id.receiverTime);
            receiverImage = itemView.findViewById(R.id.receiverImage);
            receiverImageLayout = itemView.findViewById(R.id.imageConstraintLayoutReceiver);
        }
    }

    public class SenderViewHolder extends RecyclerView.ViewHolder {

        TextView senderMsg, senderTime;
        ImageView senderImage;
        ConstraintLayout senderImageLayout;
        ConstraintLayout senderTextLayout;

        public SenderViewHolder(@NonNull View itemView) {
            super(itemView);

            senderMsg = itemView.findViewById(R.id.senderText);
            senderTime = itemView.findViewById(R.id.senderTime);
            senderImage = itemView.findViewById(R.id.senderImage);
            senderImageLayout = itemView.findViewById(R.id.imageConstraintLayoutSender);
            senderTextLayout = itemView.findViewById(R.id.textConstraintLayoutSender);
        }
    }
}

ChatActivity.java -

package com.codinggeekers.lmsbeta;

import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

import com.codinggeekers.lmsbeta.Adapter.ChatAdapter;
import com.codinggeekers.lmsbeta.Models.MessageModel;

import com.codinggeekers.lmsbeta.databinding.ActivityChatBinding;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.Date;

public class ChatActivity extends AppCompatActivity {

    ActivityChatBinding binding;

    ProgressDialog dialog;

    FirebaseAuth auth;
    FirebaseDatabase database;
    FirebaseStorage storage;

    ActivityResultLauncher<String> galleryLauncher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityChatBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        auth = FirebaseAuth.getInstance();
        database = FirebaseDatabase.getInstance();
        storage = FirebaseStorage.getInstance();

        dialog = new ProgressDialog(this);

        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setTitle("Sending Image...");
        dialog.setMessage("Please wait...");
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);

        // Sender and Receiver Ids
        final String senderId = auth.getUid();
        String receiveId = getIntent().getStringExtra("userId");
        String userName = getIntent().getStringExtra("userName");
        String profilePic = getIntent().getStringExtra("profilePic");

        binding.userName.setText(userName);
        Picasso.get().load(profilePic).placeholder(R.drawable.avatar).into(binding.profileImage);

        binding.backArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(ChatActivity.this, UsersChatActivity.class);
                startActivity(intent);
            }
        });

        final ArrayList<MessageModel> messageModels = new ArrayList<MessageModel>();

        final ChatAdapter chatAdapter = new ChatAdapter(messageModels, this);
        binding.chatRecyclerView.setAdapter(chatAdapter);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setStackFromEnd(true);
        binding.chatRecyclerView.setHasFixedSize(true);
        binding.chatRecyclerView.setLayoutManager(layoutManager);

        final String senderRoom = senderId + receiveId;
        final String receiverRoom = receiveId + senderId;

        database.getReference().child("Chats")
                .child(senderRoom)
                .addValueEventListener(new ValueEventListener() {
                    @SuppressLint("NotifyDataSetChanged")
                    @Override
                    public void onDataChange(@NonNull DataSnapshot snapshot) {
                        messageModels.clear();
                        for (DataSnapshot snapshot1 : snapshot.getChildren()) {
                            MessageModel model = snapshot1.getValue(MessageModel.class);
                            messageModels.add(model);
                        }
                        chatAdapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError error) {

                    }
                });

        binding.sendMessage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String message = binding.etMessage.getText().toString();
                if (message.matches("")) {

                } else {
                    final MessageModel model = new MessageModel(senderId, message, "text");
                    model.setTimestamp(new Date().getTime());
                    binding.etMessage.setText("");
                    database.getReference().child("Chats")
                            .child(senderRoom)
                            .push()
                            .setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(@NonNull Void unused) {
                            database.getReference().child("Chats").child(receiverRoom).push().setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                                @Override
                                public void onSuccess(@NonNull Void unused) {

                                }
                            });
                        }
                    });
                }
            }
        });

        binding.sendMessageImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                galleryLauncher.launch("image/*");
            }
        });

        galleryLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), new ActivityResultCallback<Uri>() {
            @Override
            public void onActivityResult(Uri result) {
                dialog.show();
                final StorageReference reference = storage.getReference().child("chats")
                        .child(senderRoom).child(new Date().getTime() + "");
                reference.putFile(result).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        reference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(Uri uri) {
                                final MessageModel model = new MessageModel(senderId, new Date().getTime(), uri.toString(), "image");
                                database.getReference()
                                        .child("Chats")
                                        .child(senderRoom)
                                        .push()
                                        .setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                                    @Override
                                    public void onSuccess(Void unused) {
                                        database.getReference().child("Chats").child(receiverRoom).push().setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
                                            @Override
                                            public void onSuccess(Void unused) {
                                                dialog.dismiss();
                                                binding.sendMessageImage.setImageURI(Uri.EMPTY);
                                                Intent intent = getIntent();
                                                finish();
                                                startActivity(intent);
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                });
            }
        });

        binding.userName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(ChatActivity.this, FriendsProfileActivity.class);
                intent.putExtra("userName", userName);
                intent.putExtra("userId", receiveId);
                intent.putExtra("profilePic", profilePic);
                startActivity(intent);
            }
        });

    }
}

Body:
ItemViewType should start at 0.

Try to change them to this:

    int SENDER_VIEW_TYPE = 0;
    int RECEIVER_VIEW_TYPE = 1;


来源: stackexchange

问:
I'm having error while creating React app
EPERM operation not permitted,MkDir c:command not found create react app
Npx Create-react-app myap</p>

答:
Which OS do you use ?
If it's linux or mac try to use "sudo npx create-react-app myapp".
You could do this on windows too if you use bach.</p>

ContentLicense: CC BY-SA 4.0


问:
Use 'LookAt' to look at GameObject but only on the x-z plane
```<code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class tankGunLook : MonoBehaviour
{
    public GameObject Vehicle;

    private Vector3 target = new Vector3(Vehicle.transform.x, 0, Vehicle.transform.z);

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Vehicle != null)
        {
            transform.LookAt(target);
        }
    }
}
</code>```

ERROR: Assets\Scripts\tankGunLook.cs(9,66): error CS0236: A field initializer cannot reference the non-static field, method, or property 'tankGunLook.Vehicle'

I don't quite understand what is not working here, I want the Tank Gun to look at the player or vehicle and but I don't want it to move on the y-axis. So I used 'Vehicle.transform.x' to get the x position but I guess it isn't actually getting it?

Then I want to get the y-position of the Tank Gun itself so it stays stationary but when I do this

ERROR: Assets\Scripts\tankGunLook.cs(9,45): error CS0027: Keyword 'this' is not available in the current context

答:
```<code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class tankGunLook : MonoBehaviour
{
    public GameObject Vehicle;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        Vector3 target = new Vector3(Vehicle.transform.position.x, transform.position.y, Vehicle.transform.position.z);
        transform.LookAt(target);
    }
}
</code>```

I fixed it. I'm not sure how but I assume it's something regarding the fact that the x, y and z positions are constantly updating so they need to be put in the updating section.

Body:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class tankGunLook : MonoBehaviour
{
    public GameObject Vehicle;

    private Vector3 target = new Vector3(Vehicle.transform.x, 0, Vehicle.transform.z);

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Vehicle != null)
        {
            transform.LookAt(target);
        }
    }
}

ERROR: Assets\Scripts\tankGunLook.cs(9,66): error CS0236: A field initializer cannot reference the non-static field, method, or property 'tankGunLook.Vehicle'

I don't quite understand what is not working here, I want the Tank Gun to look at the player or vehicle and but I don't want it to move on the y-axis. So I used 'Vehicle.transform.x' to get the x position but I guess it isn't actually getting it?

Then I want to get the y-position of the Tank Gun itself so it stays stationary but when I do this

ERROR: Assets\Scripts\tankGunLook.cs(9,45): error CS0027: Keyword 'this' is not available in the current context

Body:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class tankGunLook : MonoBehaviour
{
    public GameObject Vehicle;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        Vector3 target = new Vector3(Vehicle.transform.position.x, transform.position.y, Vehicle.transform.position.z);
        transform.LookAt(target);
    }
}

I fixed it. I'm not sure how but I assume it's something regarding the fact that the x, y and z positions are constantly updating so they need to be put in the updating section.


问:
Join available sizes per product in MySql
I have 6 tables:

products

id

category

active

product_versions

id

product_id

color

size_id

active

sizes

id

order

size_content

id

size_id

name

lang

product_properties

id

product_id

property_id

properties

id

name

The point is to get the following result:

product
name
size

1
XS
1

1
S
2

1
M
3

1
L
4

1
XL
5

2
XS
1

2
S
2

3
XS
1

3
S
2

3
M
3

As the product_versions has rows like this:

product
color
size

1
1
1

1
1
2

1
1
3

1
1
4

1
1
5

1
2
1

1
2
2

1
2
3

1
2
4

1
2
5

1
3
1

1
3
2

1
3
3

1
3
4

1
3
5

The following SQL works like I need, but I'd like to know, if is it possible to make it faster. Now the result is something about 0,04s at 151 rows.

My idea is to not join all product_versions rows, only one per product+size. I need to know only what sizes are available in what products. For example, if the product has 30 colors and each has 7 available sizes (210 rows per product), I only need to know 7 rows of combination product-size as fast as possible.

In my SQL I'm using GROUP BY CONCAT(product_versions.product_id,product_versions.size_id). If I remove this, there are 3083 rows which need to be grouped. I think, if I didn't have to see all product_versions rows, only one size per product, it should be much faster.

```<code>SELECT
    products.id AS product,
    size_content.name,
    sizes.id AS size
FROM
    size_content
JOIN sizes ON sizes.id = size_content.size_id
JOIN product_versions ON product_versions.size_id = sizes.id AND product_versions.active = 1
JOIN products ON products.id = product_versions.product_id AND products.active = 1
JOIN product_properties ON product_properties.product_id = products.id
WHERE
    size_content.lang = "en" AND products.category = 2 AND product_properties.property_id IN(14, 83, 106)
GROUP BY
    CONCAT(
        product_versions.product_id,
        product_versions.size_id
    )
ORDER BY
    sizes.order ASC
</code>```

Explain

Do you guys have any idea how to make it better?

Thank you.

答:
Adding these indexes may speed up MySQL; I don't know about Postgres:

```<code>products:  INDEX(category, id,  active)
size_content:  INDEX(lang, size_id,  name)
product_versions:  INDEX(size_id, product_id,  active)
product_versions:  INDEX(product_id, size_id,  active)
product_properties:  INDEX(property_id, product_id)
</code>```

When adding a composite index, DROP index(es) with the same leading columns.
That is, when you have both INDEX(a) and INDEX(a,b), toss the former.

There is no advantage in using CONCAT in a GROUP BY.  Actually, there is likely to be a big disadvantage in doing so -- it prevents the use of an index and forces collecting data in a temp for sorting.  (To be fair, no index is likely to be used by this query if you simply say GROUP BY  product_versions.product_id, product_versions.size_id.)

Body:
I have 6 tables:

products

id

category

active

product_versions

id

product_id

color

size_id

active

sizes

id

order

size_content

id

size_id

name

lang

product_properties

id

product_id

property_id

properties

id

name

The point is to get the following result:

product
name
size

1
XS
1

1
S
2

1
M
3

1
L
4

1
XL
5

2
XS
1

2
S
2

3
XS
1

3
S
2

3
M
3

As the product_versions has rows like this:

product
color
size

1
1
1

1
1
2

1
1
3

1
1
4

1
1
5

1
2
1

1
2
2

1
2
3

1
2
4

1
2
5

1
3
1

1
3
2

1
3
3

1
3
4

1
3
5

The following SQL works like I need, but I'd like to know, if is it possible to make it faster. Now the result is something about 0,04s at 151 rows.

My idea is to not join all product_versions rows, only one per product+size. I need to know only what sizes are available in what products. For example, if the product has 30 colors and each has 7 available sizes (210 rows per product), I only need to know 7 rows of combination product-size as fast as possible.

In my SQL I'm using GROUP BY CONCAT(product_versions.product_id,product_versions.size_id). If I remove this, there are 3083 rows which need to be grouped. I think, if I didn't have to see all product_versions rows, only one size per product, it should be much faster.

SELECT
    products.id AS product,
    size_content.name,
    sizes.id AS size
FROM
    size_content
JOIN sizes ON sizes.id = size_content.size_id
JOIN product_versions ON product_versions.size_id = sizes.id AND product_versions.active = 1
JOIN products ON products.id = product_versions.product_id AND products.active = 1
JOIN product_properties ON product_properties.product_id = products.id
WHERE
    size_content.lang = "en" AND products.category = 2 AND product_properties.property_id IN(14, 83, 106)
GROUP BY
    CONCAT(
        product_versions.product_id,
        product_versions.size_id
    )
ORDER BY
    sizes.order ASC

Explain

Do you guys have any idea how to make it better?

Thank you.

Body:
Adding these indexes may speed up MySQL; I don't know about Postgres:

products:  INDEX(category, id,  active)
size_content:  INDEX(lang, size_id,  name)
product_versions:  INDEX(size_id, product_id,  active)
product_versions:  INDEX(product_id, size_id,  active)
product_properties:  INDEX(property_id, product_id)

When adding a composite index, DROP index(es) with the same leading columns.
That is, when you have both INDEX(a) and INDEX(a,b), toss the former.

There is no advantage in using CONCAT in a GROUP BY.  Actually, there is likely to be a big disadvantage in doing so -- it prevents the use of an index and forces collecting data in a temp for sorting.  (To be fair, no index is likely to be used by this query if you simply say GROUP BY  product_versions.product_id, product_versions.size_id.)


问:
HTML Table fixed first column, cell text is not behind sticky column
I'm trying to have an html table where the first column is sticky. I followed other advice on using position: sticky. I'm also using some javascript because I'm building the table dynamically depending on the data passed to the DOM. The following code works as expected:

html

```<code><table class="table table-hover">
    <thead>
      <tr>
        <th scope="col" class="filled">Person</th>
        <th scope="col"># Items 1</th>
        <th scope="col"># Items 2</th>
        <th scope="col"># Items 3</th>
        <th scope="col"># Items 4</th>
        <th scope="col"># Items 5</th>
        <th scope="col"># Items 6</th>
    <th scope="col"># Items 7</th>
        <th scope="col"># Items 8</th>
        <th scope="col"># Items 9</th>
        <th scope="col"># Items 10</th>
        <th scope="col"># Items 11</th>
    <th scope="col"># Items 12</th>
        <th scope="col"># Items 13</th>
        <th scope="col"># Items 14</th>
        <th scope="col"># Items 15</th>
        <th scope="col"># Items 16</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td id="row_1" class="filled">Jim</td>
        <td id="row_1_col_1">64</td>
        <td id="row_1_col_2">12</td>
        <td id="row_1_col_3">33</td>
        <td id="row_1_col_4">32</td>
        <td id="row_1_col_5">59</td>
    <td id="row_1_col_6">64</td>
        <td id="row_1_col_7">12</td>
        <td id="row_1_col_8">33</td>
        <td id="row_1_col_9">32</td>
        <td id="row_1_col_10">59</td>
      </tr>
      <tr>
        <td id="row_2" class="filled">Sam</td>
        <td id="row_2_col_1">83</td>
        <td id="row_2_col_2">12</td>
        <td id="row_2_col_3">32</td>
        <td id="row_2_col_4">27</td>
        <td id="row_2_col_5">9</td>
    <td id="row_2_col_6">83</td>
        <td id="row_2_col_7">12</td>
        <td id="row_2_col_8">32</td>
        <td id="row_2_col_9">27</td>
        <td id="row_2_col_10">9</td>
      </tr>
      <tr>
        <td id="row_3" class="filled">Ted</td>
        <td id="row_3_col_1">11</td>
        <td id="row_3_col_2">39</td>
        <td id="row_3_col_3">77</td>
        <td id="row_3_col_4">68</td>
        <td id="row_3_col_5">93</td>
    <td id="row_3_col_6">11</td>
        <td id="row_3_col_7">39</td>
        <td id="row_3_col_8">77</td>
        <td id="row_3_col_9">68</td>
        <td id="row_3_col_10">93</td>
      </tr>
    </tbody>
</table>
</code>```

javascript

```<code>var rowName = [];
var cellName = [];
var numberPeople = 3;
var numberItems = 10;
var score = 5
for(var n=0; n < (numberPeople); n++) {
  for(var i = 0; i < numberItems; i++) {
    // +1 b/c starts at 0
    rowName[n] = "row_" + (n + 1) + "_col_" + (i+1);
    cellName[n] = document.createElement('td');
    document.getElementById(rowName[n]).appendChild(cellName[n]);
    switch (score) {
        case 5:
        document.getElementById(rowName[n]).style.backgroundColor = "#fff";
    document.getElementById(rowName[n]).style.opacity += "0.5";
        break;
    }
  }
}
</code>```

css

```<code>.table th:first-child,
.table td:first-child {
  position: sticky;
  left: 0;
  z-index: 6;

}

 .table .filled {
    background-color: #fff;
}
</code>```

Here is the jsfiddle link.

However, when I try to use this code in my actual webpage, it does not work as expected.  In my actual webpage, the text in the table cells that scrolls will sit over top of the sticky column (whereas in the jsfiddle, the cell text will go behind the sticky column - hidden by the background-color: #fff).

The webpage code and js is almost the same as the jsfiddle, the css is the same for both.

html

```<code><div class="container ps-4">
  <div class="row">
    <div class = "table-responsive">
      <table id="grade-table" class="table table-bordered table-sm ">
        <thead>
          <tr>
            <th scope="col" class="filled">Students</th>
            {% for obj in objective_list %}
            <th scope="col">{{ obj.objective_name }}</th>
            {% endfor %}
          </tr>
        </thead>
        <tbody>
          {% for student in student_list %}
          <tr>
            <td id="row_{{ forloop.counter }}" class="filled">{{ student }}</td>
            {% for obj in objective_list %}
                <td id="row_{{ forloop.parentloop.counter }}_col_{{ forloop.counter }}"></td>
            {% endfor %}
          </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
  </div>

</div>

<div>
</code>```

javascript

```<code>    <script>
        // gradeArray contains number of students & objectives, objective name and score for each objective
        var gradeArray = {{ grade_report|safe }};
        var numberStudent = gradeArray.shift();
        var numberObj = gradeArray.shift();

        if (numberObj > 0) {
          var obj = []
          for (var g = 0; g < numberObj; g++) {
            obj[g] = gradeArray.shift();
          }
        }

      var rowName = [];
      var studentname = [];
      var objective = [];
      var cellName = [];

      if (numberObj > 0) {
        for(var n=0; n < (numberStudent); n++) {
          for(var i = 0; i < numberObj; i++) {
            // +1 b/c starts at 0
            rowName[n] = "row_" + (n + 1) + "_col_" + (i + 1);
            cellName[n] = document.createElement('td');
            // numberObj + 2 b/c in the array one index is the name and the other is the grade
            let score = gradeArray[(n)*(numberObj+2)+i+1];
            cellName[n].innerHTML = score
            document.getElementById(rowName[n]).appendChild(cellName[n]);
            //document.getElementById(rowName[n]).style.color = "grey";
            switch (score) {
              case 'BEG':
              case 'EMG':
                document.getElementById(rowName[n]).className += "table-danger";
                break;
              case 'DEV':
                document.getElementById(rowName[n]).className += "table-warning";
                break;
              case 'APP':
              case 'PRF':
                document.getElementById(rowName[n]).className += "table-success";
                break;
              case 'APP+':
              case 'PRF+':
                document.getElementById(rowName[n]).className += "table-info";
                break;
              case 'EXT':
                document.getElementById(rowName[n]).className += "table-primary";
                break;
              case '---':
              case 'I':
                document.getElementById(rowName[n]).className += "table-secondary";
                document.getElementById(rowName[n]).style.opacity += "0.5";
                break;
            }

          }

        }
      }
    </script>
</code>```

There are a couple of tags in here from the django framework such as {{ student }} but I don't think they are problem - they're just how I'm passing data to the DOM. It's also how I iterate through the data. All of the text, colors, data, displays as expected except for the cell data/text not scrolling behind the sticky column.

My webpage is using boostrap 4, I don't know if that is causing the issue.

Edit
I have set up a demo account to see this issue live.  Here is the direct link to a page that will show issue, you may need to make your browser window a bit more narrow to bring up the table scrolling.
username: Demo
password: demodemo

答:
I just checked out your website and the following CSS changes fix the issue:

First, remove the z-index from this CSS selector (style.css):

.table th:first-child, .table td:first-child {
    position: sticky;
    left: 0;
    /* z-index: 6; */
```
<p>Instead, add a <code>z-index</code> to your <code>.filled</code> elements:</p>
<pre class="lang-css prettyprint-override"><code>.table .filled {
    background-color: #fff;
    z-index: 1;
}
</code>```

Also, in order to get rid of the rows being shown left to the row header (when scrolling), remove (or overwrite) the padding on this element (bootstrap's _grid.scss):

.row>* {
    flex-shrink: 0;
    width: 100%;
    max-width: 100%;
    padding-right: calc(var(--bs-gutter-x) * .5);
    /* padding-left: calc(var(--bs-gutter-x) * .5); */
    margin-top: var(--bs-gutter-y);
}
```

Body:
I'm trying to have an html table where the first column is sticky. I followed other advice on using position: sticky. I'm also using some javascript because I'm building the table dynamically depending on the data passed to the DOM. The following code works as expected:

html

        Person
        # Items 1
        # Items 2
        # Items 3
        # Items 4
        # Items 5
        # Items 6
    # Items 7
        # Items 8
        # Items 9
        # Items 10
        # Items 11
    # Items 12
        # Items 13
        # Items 14
        # Items 15
        # Items 16

        Jim
        64
        12
        33
        32
        59
    64
        12
        33
        32
        59

        Sam
        83
        12
        32
        27
        9
    83
        12
        32
        27
        9

        Ted
        11
        39
        77
        68
        93
    11
        39
        77
        68
        93

javascript

var rowName = [];
var cellName = [];
var numberPeople = 3;
var numberItems = 10;
var score = 5
for(var n=0; n < (numberPeople); n++) {
  for(var i = 0; i < numberItems; i++) {
    // +1 b/c starts at 0
    rowName[n] = "row_" + (n + 1) + "_col_" + (i+1);
    cellName[n] = document.createElement('td');
    document.getElementById(rowName[n]).appendChild(cellName[n]);
    switch (score) {
        case 5:
        document.getElementById(rowName[n]).style.backgroundColor = "#fff";
    document.getElementById(rowName[n]).style.opacity += "0.5";
        break;
    }
  }
}

css

.table th:first-child,
.table td:first-child {
  position: sticky;
  left: 0;
  z-index: 6;

}

 .table .filled {
    background-color: #fff;
}

Here is the jsfiddle link.

However, when I try to use this code in my actual webpage, it does not work as expected.  In my actual webpage, the text in the table cells that scrolls will sit over top of the sticky column (whereas in the jsfiddle, the cell text will go behind the sticky column - hidden by the background-color: #fff).

The webpage code and js is almost the same as the jsfiddle, the css is the same for both.

html

            Students
            {% for obj in objective_list %}
            {{ obj.objective_name }}
            {% endfor %}

          {% for student in student_list %}

            {{ student }}
            {% for obj in objective_list %}

            {% endfor %}

          {% endfor %}

javascript

There are a couple of tags in here from the django framework such as {{ student }} but I don't think they are problem - they're just how I'm passing data to the DOM. It's also how I iterate through the data. All of the text, colors, data, displays as expected except for the cell data/text not scrolling behind the sticky column.

My webpage is using boostrap 4, I don't know if that is causing the issue.

Edit
I have set up a demo account to see this issue live.  Here is the direct link to a page that will show issue, you may need to make your browser window a bit more narrow to bring up the table scrolling.
username: Demo
password: demodemo

Body:
I just checked out your website and the following CSS changes fix the issue:

First, remove the z-index from this CSS selector (style.css):

.table th:first-child, .table td:first-child {
    position: sticky;
    left: 0;
    /* z-index: 6; */

Instead, add a z-index to your .filled elements:

.table .filled {
    background-color: #fff;
    z-index: 1;
}

Also, in order to get rid of the rows being shown left to the row header (when scrolling), remove (or overwrite) the padding on this element (bootstrap's _grid.scss):

.row>* {
    flex-shrink: 0;
    width: 100%;
    max-width: 100%;
    padding-right: calc(var(--bs-gutter-x) * .5);
    /* padding-left: calc(var(--bs-gutter-x) * .5); */
    margin-top: var(--bs-gutter-y);
}


问:
MariaDB Transaction Isolation Levels
I am facing a problem, and I am trying to wrap my head around the isolation levels. To understand these isolation levels, I've read the documentation found on the MariaDB website.

The base isolation level used by InnoDB tables is stated to be REPEATABLE_READ.

Consider the following problem. I have the following two tables structure:

```<code>/** tableA **/
id INT AUTO_INCREMENT PRIMARY_KEY

/** tableB **/
id INT
claimedBy INT NULLABLE
</code>```

and also have a function, which pseudocode looks like this

```<code>/** should create a new row in "tableA", and update the rows from "tableB" which ids match the ones in the array from the input parameter, and that are null, to the id of this new row - in case the number of updated rows does not match the length of the input array, it should roll back everything **/
claim(array what) {
   - starts transaction
   - inserts a row into "tableA" and retrieve's it's id, storing it inside "variableA"
   - updates "claimedBy" to "variableA" on all rows from "tableB" that have "claimedBy" set to null and have "id" that is in "what"
   - counts the number of rows from "tableB", where "claimedBy" equals to "variableA"
     - if the count does not match the length of the "what" parameter, rolls back the transaction
     - if the count matches, commits the transaction
}
</code>```

My questions, which would help me understand isolation levels more concretly are the following:

In case two separate calls are made concurrently to this function which both have "what" arrays that intersect at any point, if I understand correctly, REPEATABLE_READ would prevent my data to become corrupted, because all the rows will be locked in the table as soon as the first update begins to perform, thus whichever function calls update is executed second, will be completely rolled back. Am I right in this? Based on the example on the official documentation it would seem like that rows are checked for the where condition and locked one-by-one. Is this the case? If yes, is it possible, that on concurrent calls to the function, both queries get rolled back? Or worse, is it possible that a deadlock would occur here?

In this concrete example, I could safely decrease the isolation level for the transaction to READ_COMMITED, which would also prevent the data corruption, but would not retain the locks for the duration of the update for rows that are not affected by the update, am I correct in this?

The lock retaining for manual TRANSACTIONS in MariaDB are for the duration of the query operation that create these locks, or for the duration of the complete transaction operation? (ie, until the transaction is either rolled back or commitd?)

FOLLOWUP QUESTION

Am I mistaken, that if using READ_COMMITED isolation, the following two concurrent calls could execute at the same time (without one, waiting for the lock of the other to be released), but not if REPEATABLE_READ isolation was used?

```<code>/** Session #1 **/
claim(array(1,2,3));

/** Session #2 **/
claim(array(4,5,6));
</code>```

答:
There's very little difference between REPEATABLE-READ and READ-COMMITTED in the scenario you describe.

The same locks are acquired in both cases. Locks are always held until the end of the transaction.

REPEATABLE-READ queries may also acquire gap locks to prevent new rows inserted, if those rows would change the result of some SELECT query. The MySQL manual explains gap locks better, and it works the same way in MariaDB: https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-gap-locks Regardless, I don't think this will be an issue.

I don't think you're at risk of a deadlock in the scenario you describe. Your UPDATE should lock all the rows examined. Rows are not locked one by one; the lock request is atomic. That is, if any of the set of examined rows cannot be locked because another session already has some or all of them locked, then the new lock request waits.

Once your UPDATE succeeds (locks are acquired and then the rows are updated), then your session has them locked and keeps them locked until the end of the transaction. Subsequently doing a count would reference only locked rows, so there's no way another session could slip in and cause a deadlock.

One subtle point about locking that you may not notice in the documentation: locking SQL statements act as if they are run in READ-COMMITTED mode, even if your transaction is REPEATABLE-READ. In other words, locks are acquired on the most recently committed version of a row, even if a non-locking SELECT query would not read the most recent version of that row. This is surprising to some programmers.

Re your comments:

I wrote a demo of the locking/nonlocking odd behavior in my answer here: How MVCC works with Lock in MySql?

Regarding releasing locks, yes, that's correct, in READ-COMMITTED mode, a lock is released if your UPDATE doesn't make any net change to the row. That is, if your update sets a column to the value that it already had. But in your case, you are changing values on rows that match your conditions. You specifically select for rows where the claimedBy is NULL, and you are setting that column to a non-NULL value.

Regarding your followup question, you don't have an index on the claimedBy column, so your query will have to at least examine all the rows. In READ-COMMITTED mode, it will be able to release the lock pretty promptly on rows that don't match the search conditions. But it would be better to have an index on claimedBy so it is able to examine only rows that match the condition. I would think it's better (if only by a slight margin) to avoid locking extra rows, instead of locking them and releasing the locks.

I don't think that transaction isolation is such an important factor in performance optimization. Choosing indexes to narrow down the set of examined rows is a much better strategy in most cases.

Title: MariaDB Transaction Isolation Levels

Body:
I am facing a problem, and I am trying to wrap my head around the isolation levels. To understand these isolation levels, I've read the documentation found on the MariaDB website.

The base isolation level used by InnoDB tables is stated to be REPEATABLE_READ.

Consider the following problem. I have the following two tables structure:

/** tableA **/
id INT AUTO_INCREMENT PRIMARY_KEY

/** tableB **/
id INT
claimedBy INT NULLABLE

and also have a function, which pseudocode looks like this

/** should create a new row in "tableA", and update the rows from "tableB" which ids match the ones in the array from the input parameter, and that are null, to the id of this new row - in case the number of updated rows does not match the length of the input array, it should roll back everything **/
claim(array what) {
   - starts transaction
   - inserts a row into "tableA" and retrieve's it's id, storing it inside "variableA"
   - updates "claimedBy" to "variableA" on all rows from "tableB" that have "claimedBy" set to null and have "id" that is in "what"
   - counts the number of rows from "tableB", where "claimedBy" equals to "variableA"
     - if the count does not match the length of the "what" parameter, rolls back the transaction
     - if the count matches, commits the transaction
}

My questions, which would help me understand isolation levels more concretly are the following:

In case two separate calls are made concurrently to this function which both have "what" arrays that intersect at any point, if I understand correctly, REPEATABLE_READ would prevent my data to become corrupted, because all the rows will be locked in the table as soon as the first update begins to perform, thus whichever function calls update is executed second, will be completely rolled back. Am I right in this? Based on the example on the official documentation it would seem like that rows are checked for the where condition and locked one-by-one. Is this the case? If yes, is it possible, that on concurrent calls to the function, both queries get rolled back? Or worse, is it possible that a deadlock would occur here?

In this concrete example, I could safely decrease the isolation level for the transaction to READ_COMMITED, which would also prevent the data corruption, but would not retain the locks for the duration of the update for rows that are not affected by the update, am I correct in this?

The lock retaining for manual TRANSACTIONS in MariaDB are for the duration of the query operation that create these locks, or for the duration of the complete transaction operation? (ie, until the transaction is either rolled back or commitd?)

FOLLOWUP QUESTION

Am I mistaken, that if using READ_COMMITED isolation, the following two concurrent calls could execute at the same time (without one, waiting for the lock of the other to be released), but not if REPEATABLE_READ isolation was used?

/** Session #1 **/
claim(array(1,2,3));

/** Session #2 **/
claim(array(4,5,6));


问:
Extracting rows from file based on another file using awk
I have two files.

File 1:

```<code>SNP Allele1 Allele2 Effect  StdErr  PVAL    Direction   HetISq  HetChiSHetDf    HetPVal
rs12266638  t   g   0.4259  0.0838  3.776e-07   +?  0.0 0.000   0   1
rs7995014   t   c   2.2910  0.5012  4.853e-06   +?  0.0 0.000   0   1
</code>```

File 2:

```<code>Chromosome Position SNP EA NEA EAF BETA SE P Direction
10 108627406 rs12266638 t g 0.991 -0.2649 0.0578 4.608e-06 -
11 116365828 rs112127824 a t 0.0327 0.4569 0.0994 4.327e-06 +
</code>```

I would like to print a file 3, based on the "SNP" column. If the SNP exists in file 2, I would like to print the whole row with all columns of file 1.

Output:

```<code>rs12266638  t   g   0.4259  0.0838  3.776e-07   +?  0.0 0.000   0   1
</code>```

I tried the following:

```<code>awk 'FNR==NR{a[$1]=$0; if(NR==1) print $0} ($1 in a) {print a[$1]}' file 1 file 2 > file 3
</code>```

But it prints different SNPs than those present in file 2.

答:
A more general solution which works for any position of the SNP field:

```<code># SO71009277.awk
BEGIN {
  fnr = 0
  while ((getline < ARGV[2]) > 0) {
    ++fnr
    if (fnr == 1) {
      for (i=1; i<=NF; i++)
        FIELDBYNAME2[$i] = i # e.g. FIELDBYNAME2["SNP"] = 3
    }
    else {
      SNP_KEY[$FIELDBYNAME2["SNP"]]
    }
  }
  close(ARGV[2])

  fnr = 0
  while ((getline < ARGV[1]) > 0) {
    ++fnr
    if (fnr == 1) {
      for (i=1; i<=NF; i++)
        FIELDBYNAME1[$i] = i # e.g. FIELDBYNAME1["SNP"] = 1
    }
    else {
      if ($FIELDBYNAME1["SNP"] in SNP_KEY)
        print $0
    }
  }
  close(ARGV[1])
}
</code>```

Call:

```<code>awk -f SO71009277.awk file1.txt file2.txt
=>
rs12266638  t   g   0.4259  0.0838  3.776e-07   +?  0.0 0.000   0   1
</code>```

Edit by Ed Morton - if you want to do the above using more idiomatic awk, it'd be:

```<code>FNR == 1 {
    for (i=1; i<=NF; i++) {
        fieldByName[(NR==FNR),$i] = i
    }
    next
}
NR == FNR {
    snpKey[$(fieldByName[1,"SNP"])] = $0
    next
}
$(fieldByName[0,"SNP"]) in snpKey {
    print snpKey[$(fieldByName[0,"SNP"])]
}
</code>```

Body:
I have two files.

File 1:

SNP Allele1 Allele2 Effect  StdErr  PVAL    Direction   HetISq  HetChiSHetDf    HetPVal
rs12266638  t   g   0.4259  0.0838  3.776e-07   +?  0.0 0.000   0   1
rs7995014   t   c   2.2910  0.5012  4.853e-06   +?  0.0 0.000   0   1

File 2:

Chromosome Position SNP EA NEA EAF BETA SE P Direction
10 108627406 rs12266638 t g 0.991 -0.2649 0.0578 4.608e-06 -
11 116365828 rs112127824 a t 0.0327 0.4569 0.0994 4.327e-06 +

I would like to print a file 3, based on the "SNP" column. If the SNP exists in file 2, I would like to print the whole row with all columns of file 1.

Output:

rs12266638  t   g   0.4259  0.0838  3.776e-07   +?  0.0 0.000   0   1

I tried the following:

awk 'FNR==NR{a[$1]=$0; if(NR==1) print $0} ($1 in a) {print a[$1]}' file 1 file 2 > file 3

But it prints different SNPs than those present in file 2.

Body:
A more general solution which works for any position of the SNP field:

# SO71009277.awk
BEGIN {
  fnr = 0
  while ((getline < ARGV[2]) > 0) {
    ++fnr
    if (fnr == 1) {
      for (i=1; i<=NF; i++)
        FIELDBYNAME2[$i] = i # e.g. FIELDBYNAME2["SNP"] = 3
    }
    else {
      SNP_KEY[$FIELDBYNAME2["SNP"]]
    }
  }
  close(ARGV[2])

  fnr = 0
  while ((getline < ARGV[1]) > 0) {
    ++fnr
    if (fnr == 1) {
      for (i=1; i<=NF; i++)
        FIELDBYNAME1[$i] = i # e.g. FIELDBYNAME1["SNP"] = 1
    }
    else {
      if ($FIELDBYNAME1["SNP"] in SNP_KEY)
        print $0
    }
  }
  close(ARGV[1])
}

Call:

awk -f SO71009277.awk file1.txt file2.txt
=>
rs12266638  t   g   0.4259  0.0838  3.776e-07   +?  0.0 0.000   0   1

Edit by Ed Morton - if you want to do the above using more idiomatic awk, it'd be:

FNR == 1 {
    for (i=1; i<=NF; i++) {
        fieldByName[(NR==FNR),$i] = i
    }
    next
}
NR == FNR {
    snpKey[$(fieldByName[1,"SNP"])] = $0
    next
}
$(fieldByName[0,"SNP"]) in snpKey {
    print snpKey[$(fieldByName[0,"SNP"])]
}


问:
Can someone explain what this eval command looking at AWS credentials is doing?
I am looking at some scripts used in our GitLab pipeline and came across the below line.

```<code>eval "$(jq -r '@sh "ACCOUNT_NAME=\(.account_name) ENVIRONMENT=\(.environment) AWS_REGION=\(.aws_region) COMPONENT=\(.component) CONTEXT=\(.context) ACCOUNT_NBR=\(.account_nbr)"')"

</code>```

What is the .account_name, .environment, etc? I have never heard of AWS storing anything in those.

Why is eval used here?

答: I believe the use of 'eval' here is simply to set the shell variables ACCOUNT_NAME, ENVIRONMENT, etc. It's doing that by using "raw" output (-r) and using '@sh' to escape those values to be valid in the shell.</p>

Body:
I am looking at some scripts used in our GitLab pipeline and came across the below line.

eval "$(jq -r '@sh "ACCOUNT_NAME=\(.account_name) ENVIRONMENT=\(.environment) AWS_REGION=\(.aws_region) COMPONENT=\(.component) CONTEXT=\(.context) ACCOUNT_NBR=\(.account_nbr)"')"

What is the .account_name, .environment, etc? I have never heard of AWS storing anything in those.

Why is eval used here?


问:
how to add javascript to asp.net user control?
I found that even I use ResolveUrl to indicates the path, it still does not work unless I add javascript in the page that user control is embeded in.

```<code><script src="<%= ResolveUrl("~/JS/jquery.js") %>" type="text/javascript"></script>
<script type="text/javascript">
 $(document).ready(function(){
       alert("aaaaa");
});
</script>
</code>```

Is there a way to add JS into user control directly?

答:
If you're talking about creating UserControl-specific javascript, I know exactly what you're talking about. There's no real easy way to do it (aside from just adding a script tag with your script and/or src), so here's what I do:

Create your user control

Create your js specific to that control in a separate .js file

At the top of your user control, put a big flowerbox type comment that lists all the file dependencies for that control. This includes CSS (maybe you have your css separated out too) and any JS files.

When you drop in a control, get in the habit of opening it up first and taking a look at your dependencies. This will ensure that you drop in the correct files too.

Also, naming your separate JS file the same thing as your User Control helps.

ContentLicense: CC BY-SA 3.0

Body:
I found that even I use ResolveUrl to indicates the path, it still does not work unless I add javascript in the page that user control is embeded in.

Is there a way to add JS into user control directly?


问:
React Map is not reading properties
I am learning react. It is showing an error. I tried many time to solve it but failed. I tried changing this.state.article with this.article but in vein- I even tried to cover this in function but it didn't work.

```<code>constructor(){
    super();
    console.log("let see If this constructor is running");
        this.state = {
            article : [],
            loading : false
        }

}
 async componentDidMount(){
  let url = "https://newsapi.org/v2/everything?q=pakistan&apiKey=api-key"
  let data  = await fetch(url);
  let parsedData = await data.json()
  console.log(parsedData);
  this.setState({article: parsedData.article})
}
</code>```

render() {

```<code>return <div>
    <div className='justify-content-center container my-5'>
    <h1>Muzamil's News - Headlines</h1>
    <div className='container row'>
     {this.state.article.map((element)=>{
      console.log("why it is not working");
      return <div key={element.url} className="col-md-4">
        <NewsItem title={element.title} description={element.description}
        urlToImage={element.urlToImage} url={element.url}></NewsItem>
      </div>
    })}
    </div>
    </div>
</div>
</code>```

答:
You are not using the API in the correct way, so try the following steps :

Go to API link and create account

The website will give you the API Key copy it and past it in your link, example https://newsapi.org/v2/everything?q=pakistan&apiKey=[Your_API_Key]

Use the correct keys of the data (use "articles" instead of "article" in fetch) :

Title: React Map is not reading properties

Body:
I am learning react. It is showing an error. I tried many time to solve it but failed. I tried changing this.state.article with this.article but in vein- I even tried to cover this in function but it didn't work.

constructor(){
    super();
    console.log("let see If this constructor is running");
        this.state = {
            article : [],
            loading : false
        }

}
 async componentDidMount(){
  let url = "https://newsapi.org/v2/everything?q=pakistan&apiKey=api-key"
  let data  = await fetch(url);
  let parsedData = await data.json()
  console.log(parsedData);
  this.setState({article: parsedData.article})
}

render() {

return

Muzamil's News - Headlines

     {this.state.article.map((element)=>{
      console.log("why it is not working");
      return

        <NewsItem title={element.title} description={element.description}
        urlToImage={element.urlToImage} url={element.url}></NewsItem>

    })}


问:
Get minutes between two working days in Java
I am trying to calculate the minutes between two Joda DateTimes or Calendars in Java.
Ofcourse this would be simple if I could use the Minutes.minutesBetween function, but I can only count the minutes between working days and 8:00 AM - 6:00 PM.

E.g.:

Startdate: 03-11-2015 16:00

  Enddate: 03-11-2015 17:00

This would be simple, as it would be exactly 60 minutes. Because it's a workday and between the given work hours.

Now what I am trying to calculate is:

Startdate: 03-11-2015 17:00

  Enddate: 03-12-2015 09:00

This should return 120 minutes even though there's a lot more minutes in between, because there's only two working hours between the two dates.

Sometimes there's also a weekend between two dates, those minutes should not be added either.

I have been trying tirelessly to implement this, but I have not found a solution.

Any ideas?

Thanks in advance.

EDIT:
Thanks to Davis Broda's pseudocode I have found a solution:

```<code>private static int BEGINWORKHOUR = 8;
private static int ENDWORKHOUR = 16;

public int getWorkedMinutes(){
    Calendar start = (Calendar) this.startTime.clone();
    Calendar end = (Calendar) this.endTime.clone();

    if(start.get(Calendar.HOUR_OF_DAY) < BEGINWORKHOUR){
        start.set(Calendar.HOUR_OF_DAY, BEGINWORKHOUR);
        start.set(Calendar.MINUTE, 0);
    }

    if(end.get(Calendar.HOUR_OF_DAY) >= ENDWORKHOUR){
        end.set(Calendar.HOUR_OF_DAY, ENDWORKHOUR);
        end.set(Calendar.MINUTE, 0);
    }

    int workedMins = 0;
    while(!sameDay(start, end)){
        workedMins += workedMinsDay(start);
        start.add(Calendar.DAY_OF_MONTH, 1);
        start.set(Calendar.HOUR_OF_DAY, BEGINWORKHOUR);
        start.set(Calendar.MINUTE, 0);
    }
    workedMins += (end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE)) + ((end.get(Calendar.HOUR_OF_DAY) - start.get(Calendar.HOUR_OF_DAY))*60);
    return workedMins;
}

private int workedMinsDay(Calendar start){
    if((start.get(Calendar.DAY_OF_WEEK) == 1) || (start.get(Calendar.DAY_OF_WEEK) == 6))    return 0;
    else return (60 - start.get(Calendar.MINUTE)) + ((ENDWORKHOUR - start.get(Calendar.HOUR_OF_DAY) - 1)*60);
}

private boolean sameDay(Calendar start, Calendar end){
    if(start.get(Calendar.YEAR) == end.get(Calendar.YEAR) && start.get(Calendar.MONTH) == end.get(Calendar.MONTH) &&
            start.get(Calendar.DAY_OF_MONTH) == end.get(Calendar.DAY_OF_MONTH)) return true;
    else return false;
}
</code>```

答:
I think people on lookout for a solution of this problem will find this repo useful: https://github.com/ansshuman/silversurfer

Specifically this java code file: https://github.com/ansshuman/silversurfer/blob/main/src/com/github/ansshuman/timesurfer/TimeSurfer.java

Its method 'public Long calculateWorkingTimeInMillis(Date start, Date end)' calculates working time between two dates. Time and Space complexity both are O(1) for the program. Uses the old Date and calendar api but works properly though

Body:
I am trying to calculate the minutes between two Joda DateTimes or Calendars in Java.
Ofcourse this would be simple if I could use the Minutes.minutesBetween function, but I can only count the minutes between working days and 8:00 AM - 6:00 PM.

E.g.:

Startdate: 03-11-2015 16:00

  Enddate: 03-11-2015 17:00

This would be simple, as it would be exactly 60 minutes. Because it's a workday and between the given work hours.

Now what I am trying to calculate is:

Startdate: 03-11-2015 17:00

  Enddate: 03-12-2015 09:00

This should return 120 minutes even though there's a lot more minutes in between, because there's only two working hours between the two dates.

Sometimes there's also a weekend between two dates, those minutes should not be added either.

I have been trying tirelessly to implement this, but I have not found a solution.

Any ideas?

Thanks in advance.

EDIT:
Thanks to Davis Broda's pseudocode I have found a solution:

private static int BEGINWORKHOUR = 8;
private static int ENDWORKHOUR = 16;

public int getWorkedMinutes(){
    Calendar start = (Calendar) this.startTime.clone();
    Calendar end = (Calendar) this.endTime.clone();

    if(start.get(Calendar.HOUR_OF_DAY) < BEGINWORKHOUR){
        start.set(Calendar.HOUR_OF_DAY, BEGINWORKHOUR);
        start.set(Calendar.MINUTE, 0);
    }

    if(end.get(Calendar.HOUR_OF_DAY) >= ENDWORKHOUR){
        end.set(Calendar.HOUR_OF_DAY, ENDWORKHOUR);
        end.set(Calendar.MINUTE, 0);
    }

    int workedMins = 0;
    while(!sameDay(start, end)){
        workedMins += workedMinsDay(start);
        start.add(Calendar.DAY_OF_MONTH, 1);
        start.set(Calendar.HOUR_OF_DAY, BEGINWORKHOUR);
        start.set(Calendar.MINUTE, 0);
    }
    workedMins += (end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE)) + ((end.get(Calendar.HOUR_OF_DAY) - start.get(Calendar.HOUR_OF_DAY))*60);
    return workedMins;
}

private int workedMinsDay(Calendar start){
    if((start.get(Calendar.DAY_OF_WEEK) == 1) || (start.get(Calendar.DAY_OF_WEEK) == 6))    return 0;
    else return (60 - start.get(Calendar.MINUTE)) + ((ENDWORKHOUR - start.get(Calendar.HOUR_OF_DAY) - 1)*60);
}

private boolean sameDay(Calendar start, Calendar end){
    if(start.get(Calendar.YEAR) == end.get(Calendar.YEAR) && start.get(Calendar.MONTH) == end.get(Calendar.MONTH) &&
            start.get(Calendar.DAY_OF_MONTH) == end.get(Calendar.DAY_OF_MONTH)) return true;
    else return false;
}


问:
How to get previous 4 week sales at a level
I would like to find previous four week sales at a level in Python. Say for example

```<code>ID  Category    Date    Sales
1   AA  7/02/2022   1
1   AA  31/01/2022  3
1   AA  24/01/2022  5
1   AA  10/01/2022  7
1   AA  03/01/2022  9
2   BB  7/02/2022   2
2   BB  31/01/2022  4
2   BB  24/01/2022  6
2   BB  17/01/2022  8
2   BB  10/01/2022  10
</code>```

For 1 AA 7/02/2022 sum of last four weeks will be 9 (as 17/01/2022 bales is not there and must include current row date)

Body:
I would like to find previous four week sales at a level in Python. Say for example

ID  Category    Date    Sales
1   AA  7/02/2022   1
1   AA  31/01/2022  3
1   AA  24/01/2022  5
1   AA  10/01/2022  7
1   AA  03/01/2022  9
2   BB  7/02/2022   2
2   BB  31/01/2022  4
2   BB  24/01/2022  6
2   BB  17/01/2022  8
2   BB  10/01/2022  10

For 1 AA 7/02/2022 sum of last four weeks will be 9 (as 17/01/2022 bales is not there and must include current row date)

Body:
You could set the date as index, groupby Category and take the sum of a 28-day rolling window of Sales:

import pandas as pd
import io

data = '''ID  Category    Date    Sales
1   AA  7/02/2022   1
1   AA  31/01/2022  3
1   AA  24/01/2022  5
1   AA  10/01/2022  7
1   AA  03/01/2022  9
2   BB  7/02/2022   2
2   BB  31/01/2022  4
2   BB  24/01/2022  6
2   BB  17/01/2022  8
2   BB  10/01/2022  10'''

df = pd.read_csv(io.StringIO(data), sep='\s+')
df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y')

result_df = df.set_index('Date').sort_index().groupby('Category')['Sales'].rolling("28D").sum().reset_index()

Output:

Category
Date
Sales

0
AA
2022-01-03 00:00:00
9

1
AA
2022-01-10 00:00:00
16

2
AA
2022-01-24 00:00:00
21

3
AA
2022-01-31 00:00:00
15

4
AA
2022-02-07 00:00:00
9

5
BB
2022-01-10 00:00:00
10

6
BB
2022-01-17 00:00:00
18

7
BB
2022-01-24 00:00:00
24

8
BB
2022-01-31 00:00:00
28

9
BB
2022-02-07 00:00:00
20